home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / plug_in.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-05-14  |  88.1 KB  |  3,643 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #ifdef HAVE_SYS_PARAM_H
  22. #include <sys/param.h>
  23. #endif
  24.  
  25. #include <glib.h>
  26.  
  27. #include <errno.h>
  28. #include <signal.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <string.h>
  32. #ifdef HAVE_SYS_WAIT_H
  33. #include <sys/wait.h>
  34. #endif
  35. #ifdef HAVE_SYS_TIME_H
  36. #include <sys/time.h>
  37. #endif
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <time.h>
  41. #ifdef HAVE_UNISTD_H
  42. #include <unistd.h>
  43. #endif
  44.  
  45. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  46. #define STRICT
  47. #include <windows.h>
  48. #include <process.h>
  49.  
  50. #ifdef G_OS_WIN32
  51. #include <fcntl.h>
  52. #include <io.h>
  53. #endif
  54.  
  55. #ifdef G_WITH_CYGWIN
  56. #define O_TEXT        0x0100    /* text file */
  57. #define _O_TEXT        0x0100    /* text file */
  58. #define O_BINARY    0x0200    /* binary file */
  59. #define _O_BINARY    0x0200    /* binary file */
  60. #endif
  61.  
  62. #endif
  63.  
  64. #ifdef __EMX__
  65. #include <fcntl.h>
  66. #include <process.h>
  67. #define _O_BINARY O_BINARY
  68. #define _P_NOWAIT P_NOWAIT
  69. #define xspawnv spawnv
  70. #endif
  71.  
  72. #ifdef HAVE_IPC_H
  73. #include <sys/ipc.h>
  74. #endif
  75.  
  76. #ifdef HAVE_SHM_H
  77. #include <sys/shm.h>
  78. #endif
  79.  
  80. #include "apptypes.h"
  81.  
  82. #include "app_procs.h"
  83. #include "appenv.h"
  84. #include "brush_select.h"  /* Need for closing dialogs */
  85. #include "drawable.h"
  86. #include "datafiles.h"
  87. #include "errors.h"
  88. #include "gdisplay.h"
  89. #include "general.h"
  90. #include "gimage.h"
  91. #include "gimprc.h"
  92. #include "gradient_select.h"
  93. #include "menus.h"
  94. #include "pattern_select.h"   /* Needed for closing pattern dialogs */
  95. #include "plug_in.h"
  96.  
  97. #include "tile.h"            /* ick. */
  98.  
  99. #include "libgimp/gimpenv.h"
  100. #include "libgimp/gimpprotocol.h"
  101. #include "libgimp/gimpwire.h"
  102. #include "libgimp/gimpparasite.h"
  103.  
  104. #include "libgimp/gimpintl.h"
  105.  
  106.  
  107. typedef struct _PlugInBlocked PlugInBlocked;
  108.  
  109. struct _PlugInBlocked
  110. {
  111.   PlugIn *plug_in;
  112.   gchar  *proc_name;
  113. };
  114.  
  115.  
  116. typedef struct _PlugInMenuEntry PlugInMenuEntry;
  117.  
  118. struct _PlugInMenuEntry
  119. {
  120.   PlugInProcDef *proc_def;
  121.   gchar         *domain;
  122.   gchar         *help_path;
  123. };
  124.  
  125.  
  126. typedef struct _PlugInHelpPathDef PlugInHelpPathDef;
  127.  
  128. struct _PlugInHelpPathDef
  129. {
  130.   gchar *prog_name;
  131.   gchar *help_path;
  132. };
  133.  
  134.  
  135. static gboolean plug_in_write             (GIOChannel         *channel,
  136.                        guint8            *buf,
  137.                            gulong             count);
  138. static gboolean plug_in_flush             (GIOChannel        *channel);
  139. static void     plug_in_push              (PlugIn            *plug_in);
  140. static void     plug_in_pop               (void);
  141. static gboolean plug_in_recv_message      (GIOChannel         *channel,
  142.                        GIOCondition          cond,
  143.                        gpointer          data);
  144. static void plug_in_handle_message        (WireMessage       *msg);
  145. static void plug_in_handle_quit           (void);
  146. static void plug_in_handle_tile_req       (GPTileReq         *tile_req);
  147. static void plug_in_handle_proc_run       (GPProcRun         *proc_run);
  148. static void plug_in_handle_proc_return    (GPProcReturn      *proc_return);
  149. static void plug_in_handle_proc_install   (GPProcInstall     *proc_install);
  150. static void plug_in_handle_proc_uninstall (GPProcUninstall   *proc_uninstall);
  151. static void plug_in_write_rc              (gchar             *filename);
  152. static void plug_in_init_file             (gchar             *filename);
  153. static void plug_in_query                 (PlugInDef         *plug_in_def);
  154. #ifdef HACK_FOR_BUG_66859
  155. static void plug_in_initialize            (PlugInDef         *plug_in_def);
  156. #endif
  157. static void plug_in_add_to_db             (void);
  158. static void plug_in_make_menu             (void);
  159. static gint plug_in_make_menu_entry       (gpointer           foo,
  160.                        PlugInMenuEntry   *menu_entry,
  161.                        gpointer           bar);
  162. static void plug_in_callback              (GtkWidget         *widget,
  163.                        gpointer           client_data);
  164. static void plug_in_proc_def_insert       (PlugInProcDef     *proc_def,
  165.                        void (* superceed_fn) (void *));
  166. static void plug_in_proc_def_dead         (void              *freed_proc_def);
  167. static void plug_in_proc_def_remove       (PlugInProcDef     *proc_def);
  168. static void plug_in_proc_def_destroy      (PlugInProcDef     *proc_def,
  169.                        gboolean           data_only);
  170.  
  171. static Argument * plug_in_temp_run       (ProcRecord *proc_rec,
  172.                       Argument   *args,
  173.                       gint        argc);
  174. static Argument * plug_in_params_to_args (GPParam    *params,
  175.                       gint        nparams,
  176.                       gboolean    full_copy);
  177. static GPParam  * plug_in_args_to_params (Argument   *args,
  178.                       gint        nargs,
  179.                       gboolean    full_copy);
  180. static void       plug_in_params_destroy (GPParam    *params,
  181.                       gint        nparams,
  182.                       gboolean    full_destroy);
  183. static void       plug_in_args_destroy   (Argument   *args,
  184.                       gint        nargs,
  185.                       gboolean    full_destroy);
  186. static void       plug_in_init_shm       (void);
  187.  
  188.  
  189. PlugIn *current_plug_in = NULL;
  190. GSList *proc_defs       = NULL;
  191.  
  192. static GSList *plug_in_defs     = NULL;
  193. static GSList *gimprc_proc_defs = NULL;
  194. static GSList *open_plug_ins    = NULL;
  195. static GSList *blocked_plug_ins = NULL;
  196.  
  197. static GSList *help_path_defs = NULL;
  198.  
  199. static GSList     *plug_in_stack              = NULL;
  200. static GIOChannel *current_readchannel        = NULL;
  201. static GIOChannel *current_writechannel       = NULL;
  202. static gint        current_write_buffer_index = 0;
  203. static gchar      *current_write_buffer       = NULL;
  204. static Argument   *current_return_vals        = NULL;
  205. static gint        current_return_nvals       = 0;
  206.  
  207. static ProcRecord *last_plug_in = NULL;
  208.  
  209. static gint    shm_ID = -1;
  210. static guchar *shm_addr = NULL;
  211.  
  212. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  213. static HANDLE shm_handle;
  214. #endif
  215.  
  216. static gboolean write_pluginrc = FALSE;
  217.  
  218. static gchar *std_plugins_domain = "gimp-std-plugins";
  219.  
  220.  
  221. static void
  222. plug_in_init_shm (void)
  223. {
  224.   /* allocate a piece of shared memory for use in transporting tiles
  225.    *  to plug-ins. if we can't allocate a piece of shared memory then
  226.    *  we'll fall back on sending the data over the pipe.
  227.    */
  228.   
  229. #ifdef HAVE_SHM_H
  230.   shm_ID = shmget (IPC_PRIVATE,
  231.                    TILE_WIDTH * TILE_HEIGHT * 4,
  232.                    IPC_CREAT | 0600);
  233.  
  234.   if (shm_ID == -1)
  235.     g_message ("shmget() failed: Disabling shared memory tile transport.");
  236.   else
  237.     {
  238.       shm_addr = (guchar *) shmat (shm_ID, NULL, 0);
  239.       if (shm_addr == (guchar *) -1)
  240.     {
  241.       g_message ("shmat() failed: Disabling shared memory tile transport.");
  242.       shmctl (shm_ID, IPC_RMID, NULL);
  243.       shm_ID = -1;
  244.     }
  245.       
  246. #ifdef    IPC_RMID_DEFERRED_RELEASE
  247.       if (shm_addr != (guchar *) -1)
  248.     shmctl (shm_ID, IPC_RMID, NULL);
  249. #endif
  250.     }
  251. #else
  252. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  253.   /* Use Win32 shared memory mechanisms for
  254.    * transfering tile data.
  255.    */
  256.   gint  pid;
  257.   gchar fileMapName[MAX_PATH];
  258.   gint  tileByteSize = TILE_WIDTH * TILE_HEIGHT * 4;
  259.   
  260.   /* Our shared memory id will be our process ID */
  261.   pid = GetCurrentProcessId ();
  262.   
  263.   /* From the id, derive the file map name */
  264.   g_snprintf (fileMapName, sizeof (fileMapName), "GIMP%d.SHM", pid);
  265.  
  266.   /* Create the file mapping into paging space */
  267.   shm_handle = CreateFileMapping ((HANDLE) 0xFFFFFFFF, NULL,
  268.                   PAGE_READWRITE, 0,
  269.                   tileByteSize, fileMapName);
  270.   
  271.   if (shm_handle)
  272.     {
  273.       /* Map the shared memory into our address space for use */
  274.       shm_addr = (guchar *) MapViewOfFile(shm_handle,
  275.                       FILE_MAP_ALL_ACCESS,
  276.                       0, 0, tileByteSize);
  277.       
  278.       /* Verify that we mapped our view */
  279.       if (shm_addr)
  280.     shm_ID = pid;
  281.       else
  282.     {
  283.       g_warning ("MapViewOfFile error: %d... disabling shared memory transport\n", GetLastError());
  284.     }
  285.     }
  286.   else
  287.     {
  288.       g_warning ("CreateFileMapping error: %d... disabling shared memory transport\n", GetLastError());
  289.     }
  290. #endif
  291. #endif
  292. }
  293.  
  294. void
  295. plug_in_init (void)
  296. {
  297.   extern gboolean use_shm;
  298.  
  299.   gchar         *filename;
  300.   GSList        *tmp;
  301.   GSList        *tmp2;
  302.   PlugInDef     *plug_in_def;
  303.   PlugInProcDef *proc_def;
  304.   gfloat         nplugins;
  305.   gfloat         nth;
  306.  
  307.   /* initialize the gimp protocol library and set the read and
  308.    *  write handlers.
  309.    */
  310.   gp_init ();
  311.   wire_set_writer (plug_in_write);
  312.   wire_set_flusher (plug_in_flush);
  313.  
  314.   /* allocate a piece of shared memory for use in transporting tiles
  315.    *  to plug-ins. if we can't allocate a piece of shared memory then
  316.    *  we'll fall back on sending the data over the pipe.
  317.    */
  318.   if (use_shm)
  319.     plug_in_init_shm ();
  320.  
  321.   /* search for binaries in the plug-in directory path */
  322.   datafiles_read_directories (plug_in_path, plug_in_init_file, MODE_EXECUTABLE);
  323.  
  324.   /* read the pluginrc file for cached data */
  325.   filename = NULL;
  326.   if (pluginrc_path)
  327.     {
  328.       if (g_path_is_absolute (pluginrc_path))
  329.         filename = g_strdup (pluginrc_path);
  330.       else
  331.         filename = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s",
  332.                     gimp_directory (), pluginrc_path);
  333.     }
  334.   else
  335.     filename = gimp_personal_rc_file ("pluginrc");
  336.  
  337.   app_init_update_status (_("Resource configuration"), filename, -1);
  338.   parse_gimprc_file (filename);
  339.  
  340.   /* query any plug-ins that have changed since we last wrote out
  341.    *  the pluginrc file.
  342.    */
  343.   tmp = plug_in_defs;
  344.   app_init_update_status (_("Plug-ins"), "", 0);
  345.   nplugins = g_slist_length (tmp);
  346.   nth = 0;
  347.   while (tmp)
  348.     {
  349.       plug_in_def = tmp->data;
  350.       tmp = tmp->next;
  351.  
  352.       app_init_update_status (NULL, plug_in_def->prog, nth / nplugins);
  353.  
  354.       if (plug_in_def->query)
  355.     {
  356.       write_pluginrc = TRUE;
  357.  
  358.       if (be_verbose)
  359.         g_print (_("query plug-in: \"%s\"\n"), plug_in_def->prog);
  360.  
  361.       plug_in_query (plug_in_def);
  362.     }
  363.  
  364.       nth++;
  365.     }
  366.  
  367.   app_init_update_status (NULL, NULL, 1.0);
  368.  
  369. #ifdef HACK_FOR_BUG_66859
  370.   /* run the plug-in init functions */
  371.   tmp = plug_in_defs;
  372.   while (tmp)
  373.     {
  374.       plug_in_def = tmp->data;
  375.       tmp = tmp->next;
  376.  
  377.       if (plug_in_def->init)
  378.     {
  379.       if (be_verbose)
  380.         g_print (_("init plug-in: \"%s\"\n"), plug_in_def->prog);
  381.  
  382.       plug_in_initialize (plug_in_def);
  383.     }
  384.     }
  385. #endif
  386.  
  387.   /* insert the proc defs */
  388.   for (tmp = gimprc_proc_defs; tmp; tmp = g_slist_next (tmp))
  389.     {
  390.       proc_def = g_new (PlugInProcDef, 1);
  391.       *proc_def = *((PlugInProcDef*) tmp->data);
  392.       plug_in_proc_def_insert (proc_def, NULL);
  393.     }
  394.  
  395.   tmp = plug_in_defs;
  396.   while (tmp)
  397.     {
  398.       plug_in_def = tmp->data;
  399.       tmp = tmp->next;
  400.  
  401.       tmp2 = plug_in_def->proc_defs;
  402.       while (tmp2)
  403.     {
  404.       proc_def = tmp2->data;
  405.       tmp2 = tmp2->next;
  406.  
  407.        proc_def->mtime = plug_in_def->mtime; 
  408.       plug_in_proc_def_insert (proc_def, plug_in_proc_def_dead);
  409.     }
  410.     }
  411.  
  412.   /* write the pluginrc file if necessary */
  413.   if (write_pluginrc)
  414.     {
  415.       if (be_verbose)
  416.     g_print (_("writing \"%s\"\n"), filename);
  417.  
  418.       plug_in_write_rc (filename);
  419.     }
  420.  
  421.   g_free (filename);
  422.  
  423.   /* add the plug-in procs to the procedure database */
  424.   plug_in_add_to_db ();
  425.  
  426.   /* make the menu */
  427.   plug_in_make_menu ();
  428.  
  429.   /* run the available extensions */
  430.   if (be_verbose)
  431.     g_print (_("Starting extensions: "));
  432.  
  433.   app_init_update_status (_("Extensions"), "", 0);
  434.  
  435.   tmp = proc_defs;
  436.   nplugins = g_slist_length (tmp); nth = 0;
  437.  
  438.   while (tmp)
  439.     {
  440.       proc_def = tmp->data;
  441.       tmp = tmp->next;
  442.  
  443.       if (proc_def->prog &&
  444.       (proc_def->db_info.num_args == 0) &&
  445.       (proc_def->db_info.proc_type == PDB_EXTENSION))
  446.     {
  447.       if (be_verbose)
  448.         g_print ("%s ", proc_def->db_info.name);
  449.  
  450.       app_init_update_status (NULL, proc_def->db_info.name,
  451.                   nth / nplugins);
  452.  
  453.       plug_in_run (&proc_def->db_info, NULL, 0, FALSE, TRUE, -1);
  454.     }
  455.     }
  456.  
  457.   app_init_update_status (NULL, NULL, 1.0);
  458.  
  459.   if (be_verbose)
  460.     g_print ("\n");
  461.  
  462.   /* create help path list and free up stuff */
  463.   for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
  464.     {
  465.       plug_in_def = tmp->data;
  466.  
  467.       if (plug_in_def->help_path)
  468.     {
  469.       PlugInHelpPathDef *help_path_def;
  470.  
  471.       help_path_def = g_new (PlugInHelpPathDef, 1);
  472.  
  473.       help_path_def->prog_name = g_strdup (plug_in_def->prog);
  474.       help_path_def->help_path = g_strdup (plug_in_def->help_path);
  475.  
  476.       help_path_defs = g_slist_prepend (help_path_defs, help_path_def);
  477.     }
  478.  
  479.       plug_in_def_free (plug_in_def, FALSE);
  480.     }
  481.  
  482.   g_slist_free (plug_in_defs);
  483.   plug_in_defs = NULL;
  484. }
  485.  
  486.  
  487. void
  488. plug_in_kill (void)
  489. {
  490.   GSList *tmp;
  491.   PlugIn *plug_in;
  492.   
  493. #if defined(G_OS_WIN32) || defined(G_WITH_CYGWIN)
  494.   CloseHandle (shm_handle);
  495. #else
  496. #ifdef HAVE_SHM_H
  497. #ifndef    IPC_RMID_DEFERRED_RELEASE
  498.   if (shm_ID != -1)
  499.     {
  500.       shmdt ((gchar *) shm_addr);
  501.       shmctl (shm_ID, IPC_RMID, NULL);
  502.     }
  503. #else    /* IPC_RMID_DEFERRED_RELEASE */
  504.   if (shm_ID != -1)
  505.     shmdt ((gchar *) shm_addr);
  506. #endif
  507. #endif
  508. #endif
  509.  
  510.   tmp = open_plug_ins;
  511.   while (tmp)
  512.     {
  513.       plug_in = tmp->data;
  514.       tmp = tmp->next;
  515.  
  516.       plug_in_destroy (plug_in);
  517.     }
  518. }
  519.  
  520. void
  521. plug_in_add (gchar *prog,
  522.          gchar *menu_path,
  523.          gchar *accelerator)
  524. {
  525.   PlugInProcDef *proc_def;
  526.   GSList        *tmp;
  527.  
  528.   g_return_if_fail (prog != NULL);
  529.  
  530.   if (strncmp ("plug_in_", prog, 8) != 0)
  531.     {
  532.       gchar *t = g_strdup_printf ("plug_in_%s", prog);
  533.       g_free (prog);
  534.       prog = t;
  535.     }
  536.  
  537.   tmp = gimprc_proc_defs;
  538.   while (tmp)
  539.     {
  540.       proc_def = tmp->data;
  541.       tmp = tmp->next;
  542.  
  543.       if (strcmp (proc_def->db_info.name, prog) == 0)
  544.     {
  545.       if (proc_def->db_info.name)
  546.         g_free (proc_def->db_info.name);
  547.       if (proc_def->menu_path)
  548.         g_free (proc_def->menu_path);
  549.       if (proc_def->accelerator)
  550.         g_free (proc_def->accelerator);
  551.       if (proc_def->extensions)
  552.         g_free (proc_def->extensions);
  553.       if (proc_def->prefixes)
  554.         g_free (proc_def->prefixes);
  555.       if (proc_def->magics)
  556.         g_free (proc_def->magics);
  557.       if (proc_def->image_types)
  558.         g_free (proc_def->image_types);
  559.  
  560.       proc_def->db_info.name = prog;
  561.       proc_def->menu_path    = menu_path;
  562.       proc_def->accelerator  = accelerator;
  563.       proc_def->prefixes     = NULL;
  564.       proc_def->extensions   = NULL;
  565.       proc_def->magics       = NULL;
  566.       proc_def->image_types  = NULL;
  567.       return;
  568.     }
  569.     }
  570.  
  571.   proc_def = g_new0 (PlugInProcDef, 1);
  572.   proc_def->db_info.name = prog;
  573.   proc_def->menu_path    = menu_path;
  574.   proc_def->accelerator  = accelerator;
  575.  
  576.   gimprc_proc_defs = g_slist_prepend (gimprc_proc_defs, proc_def);
  577. }
  578.  
  579. gchar *
  580. plug_in_image_types (gchar *name)
  581. {
  582.   PlugInDef     *plug_in_def;
  583.   PlugInProcDef *proc_def;
  584.   GSList        *tmp;
  585.  
  586.   g_return_val_if_fail (name != NULL, NULL);
  587.  
  588.   if (current_plug_in)
  589.     {
  590.       plug_in_def = current_plug_in->user_data;
  591.       tmp = plug_in_def->proc_defs;
  592.     }
  593.   else
  594.     {
  595.       tmp = proc_defs;
  596.     }
  597.  
  598.   while (tmp)
  599.     {
  600.       proc_def = tmp->data;
  601.       tmp = tmp->next;
  602.  
  603.       if (strcmp (proc_def->db_info.name, name) == 0)
  604.     return proc_def->image_types;
  605.     }
  606.  
  607.   return NULL;
  608. }
  609.  
  610. GSList *
  611. plug_in_extensions_parse (gchar *extensions)
  612. {
  613.   GSList *list;
  614.   gchar  *extension;
  615.   gchar  *next_token;
  616.  
  617.   list = NULL;
  618.  
  619.   /* EXTENSIONS can be NULL.  Avoid calling strtok if it is.  */
  620.   if (extensions)
  621.     {
  622.       extensions = g_strdup (extensions);
  623.       next_token = extensions;
  624.       extension = strtok (next_token, " \t,");
  625.       while (extension)
  626.     {
  627.       list = g_slist_prepend (list, g_strdup (extension));
  628.       extension = strtok (NULL, " \t,");
  629.     }
  630.       g_free (extensions);
  631.     }
  632.  
  633.   return g_slist_reverse (list);
  634. }
  635.  
  636. void
  637. plug_in_add_internal (PlugInProcDef *proc_def)
  638. {
  639.   proc_defs = g_slist_prepend (proc_defs, proc_def);
  640. }
  641.  
  642. PlugInProcDef *
  643. plug_in_file_handler (gchar *name,
  644.               gchar *extensions,
  645.               gchar *prefixes,
  646.               gchar *magics)
  647. {
  648.   PlugInDef     *plug_in_def;
  649.   PlugInProcDef *proc_def;
  650.   GSList        *tmp;
  651.  
  652.   g_return_val_if_fail (name != NULL, NULL);
  653.  
  654.   if (current_plug_in)
  655.     {
  656.       plug_in_def = current_plug_in->user_data;
  657.       tmp = plug_in_def->proc_defs;
  658.     }
  659.   else
  660.     {
  661.       tmp = proc_defs;
  662.     }
  663.  
  664.   while (tmp)
  665.     {
  666.       proc_def = tmp->data;
  667.       tmp = tmp->next;
  668.  
  669.       if (strcmp (proc_def->db_info.name, name) == 0)
  670.     {
  671.       /* EXTENSIONS can be proc_def->extensions  */
  672.       if (proc_def->extensions != extensions)
  673.         {
  674.           if (proc_def->extensions)
  675.         g_free (proc_def->extensions);
  676.           proc_def->extensions = g_strdup (extensions);
  677.         }
  678.       proc_def->extensions_list = plug_in_extensions_parse (proc_def->extensions);
  679.  
  680.       /* PREFIXES can be proc_def->prefixes  */
  681.       if (proc_def->prefixes != prefixes)
  682.         {
  683.           if (proc_def->prefixes)
  684.         g_free (proc_def->prefixes);
  685.           proc_def->prefixes = g_strdup (prefixes);
  686.         }
  687.       proc_def->prefixes_list = plug_in_extensions_parse (proc_def->prefixes);
  688.  
  689.       /* MAGICS can be proc_def->magics  */
  690.       if (proc_def->magics != magics)
  691.         {
  692.           if (proc_def->magics)
  693.         g_free (proc_def->magics);
  694.           proc_def->magics = g_strdup (magics);
  695.         }
  696.       proc_def->magics_list = plug_in_extensions_parse (proc_def->magics);
  697.       return proc_def;
  698.     }
  699.     }
  700.  
  701.   return NULL;
  702. }
  703.  
  704.  
  705. PlugInDef *
  706. plug_in_def_new (gchar *prog)
  707. {
  708.   PlugInDef *plug_in_def;
  709.  
  710.   g_return_val_if_fail (prog != NULL, NULL);
  711.  
  712.   plug_in_def = g_new (PlugInDef, 1);
  713.  
  714.   plug_in_def->prog          = g_strdup (prog);
  715.   plug_in_def->proc_defs     = NULL;
  716.   plug_in_def->locale_domain = NULL;
  717.   plug_in_def->locale_path   = NULL;
  718.   plug_in_def->help_path     = NULL;
  719.   plug_in_def->mtime         = 0;
  720.   plug_in_def->query         = FALSE;
  721. #ifdef HACK_FOR_BUG_66859
  722.   plug_in_def->init         = FALSE;
  723. #endif
  724.   
  725.   return plug_in_def;
  726. }
  727.  
  728.  
  729. void
  730. plug_in_def_free (PlugInDef *plug_in_def,
  731.           gboolean   free_proc_defs)
  732. {
  733.   GSList *list;
  734.  
  735.   g_free (plug_in_def->prog);
  736.   if (plug_in_def->locale_domain)
  737.     g_free (plug_in_def->locale_domain);
  738.   if (plug_in_def->locale_path)
  739.     g_free (plug_in_def->locale_path);
  740.   if (plug_in_def->help_path)
  741.     g_free (plug_in_def->help_path);
  742.  
  743.   if (free_proc_defs)
  744.     {
  745.       for (list = plug_in_def->proc_defs; list; list = list->next)
  746.     plug_in_proc_def_destroy ((PlugInProcDef *)(list->data), FALSE);
  747.     }
  748.  
  749.   if (plug_in_def->proc_defs)
  750.     g_slist_free (plug_in_def->proc_defs);
  751.  
  752.   g_free (plug_in_def);
  753. }
  754.  
  755.  
  756. void
  757. plug_in_def_add (PlugInDef *plug_in_def)
  758. {
  759.   PlugInDef     *tplug_in_def;
  760.   PlugInProcDef *proc_def;
  761.   GSList *tmp;
  762.   gchar  *t1, *t2;
  763.  
  764.   t1 = g_basename (plug_in_def->prog);
  765.  
  766.   /*  If this is a file load or save plugin, make sure we have
  767.    *  something for one of the extensions, prefixes, or magic number.
  768.    *  Other bits of code rely on detecting file plugins by the presence
  769.    *  of one of these things, but Nick Lamb's alien/unknown format
  770.    *  loader needs to be able to register no extensions, prefixes or
  771.    *  magics. -- austin 13/Feb/99
  772.    */
  773.   for (tmp = plug_in_def->proc_defs; tmp; tmp = g_slist_next (tmp))
  774.     {
  775.       proc_def = tmp->data;
  776.  
  777.       if (!proc_def->extensions && !proc_def->prefixes && !proc_def->magics &&
  778.       proc_def->menu_path &&
  779.       (!strncmp (proc_def->menu_path, "<Load>", 6) ||
  780.        !strncmp (proc_def->menu_path, "<Save>", 6)))
  781.     {
  782.       proc_def->extensions = g_strdup ("");
  783.     }
  784.     }
  785.  
  786.   for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
  787.     {
  788.       tplug_in_def = tmp->data;
  789.  
  790.       t2 = g_basename (tplug_in_def->prog);
  791.  
  792.       if (strcmp (t1, t2) == 0)
  793.     {
  794.       if ((g_strcasecmp (plug_in_def->prog, tplug_in_def->prog) == 0) &&
  795.           (plug_in_def->mtime == tplug_in_def->mtime))
  796.         {
  797.           /* Use cached plug-in entry */
  798.           tmp->data = plug_in_def;
  799.           plug_in_def_free (tplug_in_def, TRUE);
  800.         }
  801.       else
  802.         {
  803.           plug_in_def_free (plug_in_def, TRUE);    
  804.         }
  805.       
  806.       return;
  807.     }
  808.     }
  809.  
  810.   write_pluginrc = TRUE;
  811.   g_print ("\"%s\" executable not found\n", plug_in_def->prog);
  812.   plug_in_def_free (plug_in_def, FALSE);
  813. }
  814.  
  815. gchar *
  816. plug_in_menu_path (gchar *name)
  817. {
  818.   PlugInDef *plug_in_def;
  819.   PlugInProcDef *proc_def;
  820.   GSList *tmp, *tmp2;
  821.  
  822.   g_return_val_if_fail (name != NULL, NULL);
  823.  
  824.   for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
  825.     {
  826.       plug_in_def = tmp->data;
  827.  
  828.       for (tmp2 = plug_in_def->proc_defs; tmp2; tmp2 = g_slist_next (tmp2))
  829.     {
  830.       proc_def = tmp2->data;
  831.  
  832.       if (strcmp (proc_def->db_info.name, name) == 0)
  833.         return proc_def->menu_path;
  834.     }
  835.     }
  836.  
  837.   for (tmp = proc_defs; tmp; tmp = g_slist_next (tmp))
  838.     {
  839.       proc_def = tmp->data;
  840.  
  841.       if (strcmp (proc_def->db_info.name, name) == 0)
  842.     return proc_def->menu_path;
  843.     }
  844.  
  845.   return NULL;
  846. }
  847.  
  848. gchar *
  849. plug_in_help_path (gchar *prog_name)
  850. {
  851.   PlugInHelpPathDef *help_path_def;
  852.   GSList *list;
  853.  
  854.   if (!prog_name || !strlen (prog_name))
  855.     return NULL;
  856.  
  857.   for (list = help_path_defs; list; list = g_slist_next (list))
  858.     {
  859.       help_path_def = (PlugInHelpPathDef *) list->data;
  860.  
  861.       if (help_path_def &&
  862.       help_path_def->prog_name &&
  863.       strcmp (help_path_def->prog_name, prog_name) == 0)
  864.     return help_path_def->help_path;
  865.     }
  866.  
  867.   return NULL;
  868. }
  869.  
  870. PlugIn *
  871. plug_in_new (gchar *name)
  872. {
  873.   PlugIn *plug_in;
  874.   gchar  *path;
  875.  
  876.   if (!g_path_is_absolute (name))
  877.     {
  878.       path = search_in_path (plug_in_path, name);
  879.       if (!path)
  880.     {
  881.       g_message (_("Unable to locate Plug-In: \"%s\""), name);
  882.       return NULL;
  883.     }
  884.     }
  885.   else
  886.     {
  887.       path = name;
  888.     }
  889.  
  890.   plug_in = g_new (PlugIn, 1);
  891.  
  892.   plug_in->open               = FALSE;
  893.   plug_in->destroy            = FALSE;
  894.   plug_in->query              = FALSE;
  895. #ifdef HACK_FOR_BUG_66859
  896.   plug_in->init               = FALSE;
  897. #endif
  898.   plug_in->synchronous        = FALSE;
  899.   plug_in->recurse            = FALSE;
  900.   plug_in->busy               = FALSE;
  901.   plug_in->pid                = 0;
  902.   plug_in->args[0]            = g_strdup (path);
  903.   plug_in->args[1]            = g_strdup ("-gimp");
  904.   plug_in->args[2]            = NULL;
  905.   plug_in->args[3]            = NULL;
  906.   plug_in->args[4]            = NULL;
  907.   plug_in->args[5]            = NULL;
  908.   plug_in->args[6]            = NULL;
  909.   plug_in->my_read            = NULL;
  910.   plug_in->my_write           = NULL;
  911.   plug_in->his_read           = NULL;
  912.   plug_in->his_write          = NULL;
  913.   plug_in->input_id           = 0;
  914.   plug_in->write_buffer_index = 0;
  915.   plug_in->temp_proc_defs     = NULL;
  916.   plug_in->progress           = NULL;
  917.   plug_in->user_data          = NULL;
  918.  
  919.   return plug_in;
  920. }
  921.  
  922. void
  923. plug_in_destroy (PlugIn *plug_in)
  924. {
  925.   if (plug_in)
  926.     {
  927.       plug_in_close (plug_in, TRUE);
  928.  
  929.       if (plug_in->args[0])
  930.     g_free (plug_in->args[0]);
  931.       if (plug_in->args[1])
  932.     g_free (plug_in->args[1]);
  933.       if (plug_in->args[2])
  934.     g_free (plug_in->args[2]);
  935.       if (plug_in->args[3])
  936.     g_free (plug_in->args[3]);
  937.       if (plug_in->args[4])
  938.     g_free (plug_in->args[4]);
  939.       if (plug_in->args[5])
  940.     g_free (plug_in->args[5]);
  941.  
  942.       if (plug_in->progress)
  943.     progress_end (plug_in->progress);
  944.       plug_in->progress = NULL;
  945.  
  946.       if (plug_in == current_plug_in)
  947.     plug_in_pop ();
  948.  
  949.       if (!plug_in->destroy)
  950.     g_free (plug_in);
  951.     }
  952. }
  953.  
  954. #ifdef G_OS_WIN32
  955. /* The Microsoft _spawnv() does not allow to run scripts. But
  956.  * this is essential to get scripting extension up and running.
  957.  * Following the replacement function xspawnv().
  958.  */
  959. gint
  960. xspawnv (gint                mode,
  961.      const gchar        *cmdname,
  962.      const gchar *const *argv)
  963. {
  964.   gchar sExecutable[_MAX_PATH*2];
  965.   gchar sCmndLine[1024];
  966.   gint i;
  967.   gint pid;
  968.  
  969.   /* only use it if _spawnv fails */
  970.   pid = _spawnv (mode, cmdname, argv);
  971.   if (pid != -1) return pid;
  972.  
  973.   /* stuff parameters into one cmndline */
  974.   sCmndLine[0] = 0;
  975.   for (i = 1; argv[i] != NULL; i++)
  976.     {
  977.        strcat (sCmndLine, argv[i]);
  978.        strcat (sCmndLine, " ");
  979.     }
  980.   /* remove last blank */
  981.   sCmndLine[strlen (sCmndLine)-1] = 0;
  982.  
  983.   /* do we really need _spawnv (ShelExecute seems not to do it)*/
  984.   if (32 <= (int) FindExecutable (cmdname, 
  985.                   gimp_directory (),
  986.                   sExecutable))
  987.     {
  988.       /* g_print("_spawnlp %s %s %s", sExecutable, cmdname, sCmndLine); */
  989.       
  990.       pid = _spawnlp (mode, sExecutable, "-c", cmdname, sCmndLine, NULL);
  991.     }
  992.   else
  993.     {
  994.       g_warning ("Execution error for: %s", cmdname);
  995.       return -1;
  996.     }
  997.   return pid;
  998. }
  999.  
  1000. #endif /* G_OS_WIN32 */
  1001.  
  1002. gboolean
  1003. plug_in_open (PlugIn *plug_in)
  1004. {
  1005.   gint my_read[2];
  1006.   gint my_write[2];
  1007.  
  1008.   if (plug_in)
  1009.     {
  1010.       /* Open two pipes. (Bidirectional communication).
  1011.        */
  1012.       if ((pipe (my_read) == -1) || (pipe (my_write) == -1))
  1013.     {
  1014.       g_message ("pipe() failed: Unable to start Plug-In \"%s\"\n(%s)",
  1015.              g_basename (plug_in->args[0]), plug_in->args[0]);
  1016.       return FALSE;
  1017.     }
  1018.  
  1019. #if defined(G_WITH_CYGWIN) || defined(__EMX__)
  1020.       /* Set to binary mode */
  1021.       setmode (my_read[0], _O_BINARY);
  1022.       setmode (my_write[0], _O_BINARY);
  1023.       setmode (my_read[1], _O_BINARY);
  1024.       setmode (my_write[1], _O_BINARY);
  1025. #endif
  1026.  
  1027.       plug_in->my_read   = g_io_channel_unix_new (my_read[0]);
  1028.       plug_in->my_write  = g_io_channel_unix_new (my_write[1]);
  1029.       plug_in->his_read  = g_io_channel_unix_new (my_write[0]);
  1030.       plug_in->his_write = g_io_channel_unix_new (my_read[1]);
  1031.  
  1032.       /* Remember the file descriptors for the pipes.
  1033.        */
  1034.       plug_in->args[2] =
  1035.     g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_read));
  1036.       plug_in->args[3] =
  1037.     g_strdup_printf ("%d", g_io_channel_unix_get_fd (plug_in->his_write));
  1038.  
  1039.       /* Set the rest of the command line arguments.
  1040.        */
  1041.       if (plug_in->query)
  1042.     {
  1043.       plug_in->args[4] = g_strdup ("-query");
  1044.     }
  1045. #ifdef HACK_FOR_BUG_66859
  1046.       else if (plug_in->init)
  1047.     {
  1048.       plug_in->args[4] = g_strdup ("-init");
  1049.     }
  1050. #endif
  1051.       else
  1052.     {
  1053.       plug_in->args[4] = g_strdup ("-run");
  1054.     }
  1055.  
  1056.       plug_in->args[5] = g_strdup_printf ("%d", (gint) stack_trace_mode);
  1057.  
  1058.       /* Fork another process. We'll remember the process id
  1059.        *  so that we can later use it to kill the filter if
  1060.        *  necessary.
  1061.        */
  1062. #ifdef __EMX__
  1063.       fcntl (my_read[0], F_SETFD, 1);
  1064.       fcntl (my_write[1], F_SETFD, 1);
  1065. #endif
  1066. #if defined(G_OS_WIN32) || defined (G_WITH_CYGWIN) || defined(__EMX__)
  1067.       plug_in->pid = xspawnv (_P_NOWAIT, plug_in->args[0], plug_in->args);
  1068.       if (plug_in->pid == -1)
  1069. #else
  1070.       plug_in->pid = fork ();
  1071.  
  1072.       if (plug_in->pid == 0)
  1073.     {
  1074.       g_io_channel_close (plug_in->my_read);
  1075.       g_io_channel_unref (plug_in->my_read);
  1076.       plug_in->my_read  = NULL;
  1077.       g_io_channel_close (plug_in->my_write);
  1078.       g_io_channel_unref (plug_in->my_write);
  1079.       plug_in->my_write  = NULL;
  1080.  
  1081.           /* Execute the filter. The "_exit" call should never
  1082.            *  be reached, unless some strange error condition
  1083.            *  exists.
  1084.            */
  1085.           execvp (plug_in->args[0], plug_in->args);
  1086.           _exit (1);
  1087.     }
  1088.       else if (plug_in->pid == -1)
  1089. #endif
  1090.     {
  1091.           g_message ("fork() failed: Unable to run Plug-In: \"%s\"\n(%s)",
  1092.              g_basename (plug_in->args[0]), plug_in->args[0]);
  1093.           plug_in_destroy (plug_in);
  1094.           return FALSE;
  1095.     }
  1096.  
  1097.       g_io_channel_close (plug_in->his_read);
  1098.       g_io_channel_unref (plug_in->his_read);
  1099.       plug_in->his_read  = NULL;
  1100.       g_io_channel_close (plug_in->his_write);
  1101.       g_io_channel_unref (plug_in->his_write);
  1102.       plug_in->his_write = NULL;
  1103.  
  1104.       if (!plug_in->synchronous)
  1105.     {
  1106.       plug_in->input_id =
  1107.         g_io_add_watch (plug_in->my_read,
  1108.                 G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
  1109.                 plug_in_recv_message,
  1110.                 plug_in);
  1111.  
  1112.       open_plug_ins = g_slist_prepend (open_plug_ins, plug_in);
  1113.     }
  1114.  
  1115.       plug_in->open = TRUE;
  1116.       return TRUE;
  1117.     }
  1118.  
  1119.   return FALSE;
  1120. }
  1121.  
  1122. void
  1123. plug_in_close (PlugIn   *plug_in,
  1124.            gboolean  kill_it)
  1125. {
  1126. #ifndef G_OS_WIN32
  1127.   gint status;
  1128.   struct timeval tv;
  1129. #endif
  1130.  
  1131.   if (plug_in && plug_in->open)
  1132.     {
  1133.       plug_in->open = FALSE;
  1134.  
  1135.       /* Ask the filter to exit gracefully
  1136.        */
  1137.       if (kill_it && plug_in->pid)
  1138.     {
  1139.       plug_in_push (plug_in);
  1140.       gp_quit_write (current_writechannel);
  1141.       plug_in_pop ();
  1142.  
  1143.       /*  give the plug-in some time (10 ms)  */
  1144. #ifndef G_OS_WIN32
  1145.       tv.tv_sec = 0;
  1146.       tv.tv_usec = 10 * 1000;
  1147.       select (0, NULL, NULL, NULL, &tv);
  1148. #else
  1149.       Sleep (10);
  1150. #endif
  1151.     }
  1152.  
  1153.       /* If necessary, kill the filter. */
  1154. #ifndef G_OS_WIN32
  1155.       if (kill_it && plug_in->pid)
  1156.     status = kill (plug_in->pid, SIGKILL);
  1157.  
  1158.       /* Wait for the process to exit. This will happen
  1159.        *  immediately if it was just killed.
  1160.        */
  1161.       if (plug_in->pid)
  1162.         waitpid (plug_in->pid, &status, 0);
  1163. #else
  1164.       if (kill_it && plug_in->pid)
  1165.     {
  1166.       /* Trying to avoid TerminateProcess (does mostly work).
  1167.        * Otherwise some of our needed DLLs may get into an unstable state
  1168.        * (see Win32 API docs).
  1169.        */
  1170.       DWORD dwExitCode = STILL_ACTIVE;
  1171.       DWORD dwTries  = 10;
  1172.       while ((STILL_ACTIVE == dwExitCode)
  1173.          && GetExitCodeProcess((HANDLE) plug_in->pid, &dwExitCode)
  1174.          && (dwTries > 0))
  1175.         {
  1176.           Sleep(10);
  1177.           dwTries--;
  1178.         }
  1179.       if (STILL_ACTIVE == dwExitCode)
  1180.         {
  1181.           g_warning("Terminating %s handle %p...",
  1182.             g_basename (plug_in->args[0]),
  1183.             (HANDLE) plug_in->pid);
  1184.           TerminateProcess ((HANDLE) plug_in->pid, 0);
  1185.         }
  1186.     }
  1187. #endif
  1188.  
  1189.       /* Remove the input handler. */
  1190.       if (plug_in->input_id)
  1191.         gdk_input_remove (plug_in->input_id);
  1192.  
  1193.       /* Close the pipes. */
  1194.       if (plug_in->my_read != NULL)
  1195.     {
  1196.       g_io_channel_close (plug_in->my_read);
  1197.       g_io_channel_unref (plug_in->my_read);
  1198.       plug_in->my_read = NULL;
  1199.     }
  1200.       if (plug_in->my_write != NULL)
  1201.     {
  1202.       g_io_channel_close (plug_in->my_write);
  1203.       g_io_channel_unref (plug_in->my_write);
  1204.       plug_in->my_write = NULL;
  1205.     }
  1206.       if (plug_in->his_read != NULL)
  1207.     {
  1208.       g_io_channel_close (plug_in->his_read);
  1209.       g_io_channel_unref (plug_in->his_read);
  1210.       plug_in->his_read = NULL;
  1211.     }
  1212.       if (plug_in->his_write != NULL)
  1213.     {
  1214.       g_io_channel_close (plug_in->his_write);
  1215.       g_io_channel_unref (plug_in->his_write);
  1216.       plug_in->his_write = NULL;
  1217.     }
  1218.  
  1219.       wire_clear_error ();
  1220.  
  1221.       /* Destroy the progress dialog if it exists. */
  1222.       if (plug_in->progress)
  1223.     progress_end (plug_in->progress);
  1224.       plug_in->progress = NULL;
  1225.  
  1226.       /* Set the fields to null values. */
  1227.       plug_in->pid = 0;
  1228.       plug_in->input_id = 0;
  1229.       plug_in->my_read = NULL;
  1230.       plug_in->my_write = NULL;
  1231.       plug_in->his_read = NULL;
  1232.       plug_in->his_write = NULL;
  1233.  
  1234.       if (plug_in->recurse)
  1235.     gtk_main_quit ();
  1236.  
  1237.       plug_in->synchronous = FALSE;
  1238.       plug_in->recurse     = FALSE;
  1239.  
  1240.       /* Unregister any temporary procedures. */
  1241.       if (plug_in->temp_proc_defs)
  1242.     {
  1243.       GSList        *list;
  1244.       PlugInProcDef *proc_def;
  1245.  
  1246.       for (list = plug_in->temp_proc_defs; list; list = g_slist_next (list))
  1247.         {
  1248.           proc_def = (PlugInProcDef *) list->data;
  1249.           plug_in_proc_def_remove (proc_def);
  1250.         }
  1251.  
  1252.       g_slist_free (plug_in->temp_proc_defs);
  1253.       plug_in->temp_proc_defs = NULL;
  1254.     }
  1255.  
  1256.       /* Close any dialogs that this plugin might have opened */
  1257.       brushes_check_dialogs ();
  1258.       patterns_check_dialogs ();
  1259.       gradients_check_dialogs ();
  1260.  
  1261.       open_plug_ins = g_slist_remove (open_plug_ins, plug_in);
  1262.     }
  1263. }
  1264.  
  1265. static Argument *
  1266. plug_in_get_current_return_vals (ProcRecord *proc_rec)
  1267. {
  1268.   Argument *return_vals;
  1269.   gint      nargs;
  1270.  
  1271.   /* Return the status code plus the current return values. */
  1272.   nargs = proc_rec->num_values + 1;
  1273.   if (current_return_vals && current_return_nvals == nargs)
  1274.     {
  1275.       return_vals = current_return_vals;
  1276.     }
  1277.   else if (current_return_vals)
  1278.     {
  1279.       /* Allocate new return values of the correct size. */
  1280.       return_vals = procedural_db_return_args (proc_rec, FALSE);
  1281.  
  1282.       /* Copy all of the arguments we can. */
  1283.       memcpy (return_vals, current_return_vals,
  1284.           sizeof (Argument) * MIN (current_return_nvals, nargs));
  1285.  
  1286.       /* Free the old argument pointer.  This will cause a memory leak
  1287.      only if there were more values returned than we need (which
  1288.      shouldn't ever happen). */
  1289.       g_free (current_return_vals);
  1290.     }
  1291.   else
  1292.     {
  1293.       /* Just return a dummy set of values. */
  1294.       return_vals = procedural_db_return_args (proc_rec, FALSE);
  1295.     }
  1296.  
  1297.   /* We have consumed any saved values, so clear them. */
  1298.   current_return_nvals = 0;
  1299.   current_return_vals  = NULL;
  1300.  
  1301.   return return_vals;
  1302. }
  1303.  
  1304. Argument *
  1305. plug_in_run (ProcRecord *proc_rec,
  1306.          Argument   *args,
  1307.          gint        argc,
  1308.          gboolean    synchronous,   
  1309.          gboolean    destroy_values,
  1310.          gint        gdisp_ID)
  1311. {
  1312.   GPConfig   config;
  1313.   GPProcRun  proc_run;
  1314.   Argument  *return_vals;
  1315.   PlugIn    *plug_in;
  1316.  
  1317.   return_vals = NULL;
  1318.  
  1319.   if (proc_rec->proc_type == PDB_TEMPORARY)
  1320.     {
  1321.       return_vals = plug_in_temp_run (proc_rec, args, argc);
  1322.       goto done;
  1323.     }
  1324.  
  1325.   plug_in = plug_in_new (proc_rec->exec_method.plug_in.filename);
  1326.  
  1327.   if (plug_in)
  1328.     {
  1329.       if (plug_in_open (plug_in))
  1330.     {
  1331.       plug_in->recurse = synchronous;
  1332.  
  1333.       plug_in_push (plug_in);
  1334.  
  1335.       config.version      = GP_VERSION;
  1336.       config.tile_width   = TILE_WIDTH;
  1337.       config.tile_height  = TILE_HEIGHT;
  1338.       config.shm_ID       = shm_ID;
  1339.       config.gamma        = gamma_val;
  1340.       config.install_cmap = install_cmap;
  1341.       config.use_xshm     = gdk_get_use_xshm ();
  1342.       config.gdisp_ID     = gdisp_ID;
  1343.  
  1344.       if (gtk_check_version (1, 2, 8))
  1345.         config.min_colors = CLAMP (min_colors, 27, 216);
  1346.       else
  1347.         config.min_colors = CLAMP (min_colors, 27, 256);
  1348.  
  1349.       proc_run.name    = proc_rec->name;
  1350.       proc_run.nparams = argc;
  1351.       proc_run.params  = plug_in_args_to_params (args, argc, FALSE);
  1352.  
  1353.       if (!gp_config_write (current_writechannel, &config) ||
  1354.           !gp_proc_run_write (current_writechannel, &proc_run) ||
  1355.           !wire_flush (current_writechannel))
  1356.         {
  1357.           return_vals = procedural_db_return_args (proc_rec, FALSE);
  1358.           goto done;
  1359.         }
  1360.  
  1361.       plug_in_pop ();
  1362.  
  1363.       plug_in_params_destroy (proc_run.params, proc_run.nparams, FALSE);
  1364.  
  1365.       /*  If this is an automatically installed extension, wait for an
  1366.        *  installation-confirmation message
  1367.        */
  1368.       if ((proc_rec->proc_type == PDB_EXTENSION) &&
  1369.           (proc_rec->num_args == 0))
  1370.         gtk_main ();
  1371.  
  1372.       if (plug_in->recurse)
  1373.         {
  1374.           gtk_main ();
  1375.           return_vals = plug_in_get_current_return_vals (proc_rec);
  1376.         }
  1377.     }
  1378.     }
  1379.  
  1380.  done:
  1381.   if (return_vals && destroy_values)
  1382.     {
  1383.       procedural_db_destroy_args (return_vals, proc_rec->num_values);
  1384.       return_vals = NULL;
  1385.     }
  1386.   return return_vals;
  1387. }
  1388.  
  1389. void
  1390. plug_in_repeat (gboolean with_interface)
  1391. {
  1392.   GDisplay *gdisplay;
  1393.   Argument *args;
  1394.   gint i;
  1395.  
  1396.   if (last_plug_in)
  1397.     {
  1398.       gdisplay = gdisplay_active ();
  1399.       if (!gdisplay) return;
  1400.  
  1401.       /* construct the procedures arguments */
  1402.       args = g_new (Argument, 3);
  1403.  
  1404.       /* initialize the first three argument types */
  1405.       for (i = 0; i < 3; i++)
  1406.     args[i].arg_type = last_plug_in->args[i].arg_type;
  1407.  
  1408.       /* initialize the first three plug-in arguments  */
  1409.       args[0].value.pdb_int = (with_interface ? RUN_INTERACTIVE : RUN_WITH_LAST_VALS);
  1410.       args[1].value.pdb_int = pdb_image_to_id (gdisplay->gimage);
  1411.       args[2].value.pdb_int = drawable_ID (gimage_active_drawable (gdisplay->gimage));
  1412.  
  1413.       /* run the plug-in procedure */
  1414.       plug_in_run (last_plug_in, args, 3, FALSE, TRUE, gdisplay->ID);
  1415.  
  1416.       g_free (args);
  1417.     }
  1418. }
  1419.  
  1420. void
  1421. plug_in_set_menu_sensitivity (GimpImageType type)
  1422. {
  1423.   PlugInProcDef *proc_def;
  1424.   GSList        *tmp;
  1425.   gboolean       sensitive = FALSE;
  1426.  
  1427.   for (tmp = proc_defs; tmp; tmp = g_slist_next (tmp))
  1428.     {
  1429.       proc_def = tmp->data;
  1430.  
  1431.       if (proc_def->image_types_val && proc_def->menu_path)
  1432.     {
  1433.       switch (type)
  1434.         {
  1435.         case RGB_GIMAGE:
  1436.           sensitive = proc_def->image_types_val & PLUG_IN_RGB_IMAGE;
  1437.           break;
  1438.         case RGBA_GIMAGE:
  1439.           sensitive = proc_def->image_types_val & PLUG_IN_RGBA_IMAGE;
  1440.           break;
  1441.         case GRAY_GIMAGE:
  1442.           sensitive = proc_def->image_types_val & PLUG_IN_GRAY_IMAGE;
  1443.           break;
  1444.         case GRAYA_GIMAGE:
  1445.           sensitive = proc_def->image_types_val & PLUG_IN_GRAYA_IMAGE;
  1446.           break;
  1447.         case INDEXED_GIMAGE:
  1448.           sensitive = proc_def->image_types_val & PLUG_IN_INDEXED_IMAGE;
  1449.           break;
  1450.         case INDEXEDA_GIMAGE:
  1451.           sensitive = proc_def->image_types_val & PLUG_IN_INDEXEDA_IMAGE;
  1452.           break;
  1453.         default:
  1454.           sensitive = FALSE;
  1455.           break;
  1456.         }
  1457.  
  1458.       menus_set_sensitive (proc_def->menu_path, sensitive);
  1459.  
  1460.           if (last_plug_in && (last_plug_in == &(proc_def->db_info)))
  1461.         {
  1462.           menus_set_sensitive ("<Image>/Filters/Repeat Last", sensitive);
  1463.           menus_set_sensitive ("<Image>/Filters/Re-Show Last", sensitive);
  1464.         }
  1465.     }
  1466.     }
  1467.  
  1468.   if (!last_plug_in)
  1469.     {
  1470.       menus_set_sensitive ("<Image>/Filters/Repeat Last", FALSE);
  1471.       menus_set_sensitive ("<Image>/Filters/Re-Show Last", FALSE);
  1472.     }
  1473. }
  1474.  
  1475. static gboolean
  1476. plug_in_recv_message (GIOChannel   *channel,
  1477.               GIOCondition  cond,
  1478.               gpointer        data)
  1479. {
  1480.   gboolean got_message = FALSE;
  1481.  
  1482.   if ((PlugIn *) data != current_plug_in)
  1483.     plug_in_push ((PlugIn *) data);
  1484.  
  1485.   if (current_readchannel == NULL)
  1486.     return TRUE;
  1487.  
  1488.   if (cond & (G_IO_IN | G_IO_PRI))
  1489.     {
  1490.       WireMessage msg;
  1491.  
  1492.       memset (&msg, 0, sizeof (WireMessage));
  1493.  
  1494.       if (!wire_read_msg (current_readchannel, &msg))
  1495.     {
  1496.       plug_in_close (current_plug_in, TRUE);
  1497.     }
  1498.       else 
  1499.     {
  1500.       plug_in_handle_message (&msg);
  1501.       wire_destroy (&msg);
  1502.       got_message = TRUE;
  1503.     }
  1504.  
  1505.     }
  1506.  
  1507.   if (cond & (G_IO_ERR | G_IO_HUP))
  1508.     {
  1509.       if (current_plug_in->open)
  1510.     {
  1511.       plug_in_close (current_plug_in, TRUE);
  1512.     }
  1513.     }
  1514.  
  1515.   if (!got_message)
  1516.     g_message (_("Plug-In crashed: \"%s\"\n(%s)\n\n"
  1517.          "The dying Plug-In may have messed up GIMP's internal state.\n"
  1518.          "You may want to save your images and restart GIMP\n"
  1519.          "to be on the safe side."),
  1520.            g_basename (current_plug_in->args[0]),
  1521.            current_plug_in->args[0]);
  1522.  
  1523.   if (!current_plug_in->open)
  1524.     plug_in_destroy (current_plug_in);
  1525.   else
  1526.     plug_in_pop ();
  1527.  
  1528.   return TRUE;
  1529. }
  1530.  
  1531. static void
  1532. plug_in_handle_message (WireMessage *msg)
  1533. {
  1534.   switch (msg->type)
  1535.     {
  1536.     case GP_QUIT:
  1537.       plug_in_handle_quit ();
  1538.       break;
  1539.     case GP_CONFIG:
  1540.       g_warning ("plug_in_handle_message(): "
  1541.          "received a config message (should not happen)");
  1542.       plug_in_close (current_plug_in, TRUE);
  1543.       break;
  1544.     case GP_TILE_REQ:
  1545.       plug_in_handle_tile_req (msg->data);
  1546.       break;
  1547.     case GP_TILE_ACK:
  1548.       g_warning ("plug_in_handle_message(): "
  1549.          "received a tile ack message (should not happen)");
  1550.       plug_in_close (current_plug_in, TRUE);
  1551.       break;
  1552.     case GP_TILE_DATA:
  1553.       g_warning ("plug_in_handle_message(): "
  1554.          "received a tile data message (should not happen)");
  1555.       plug_in_close (current_plug_in, TRUE);
  1556.       break;
  1557.     case GP_PROC_RUN:
  1558.       plug_in_handle_proc_run (msg->data);
  1559.       break;
  1560.     case GP_PROC_RETURN:
  1561.       plug_in_handle_proc_return (msg->data);
  1562.       plug_in_close (current_plug_in, FALSE);
  1563.       break;
  1564.     case GP_TEMP_PROC_RUN:
  1565.       g_warning ("plug_in_handle_message(): "
  1566.          "received a temp proc run message (should not happen)");
  1567.       plug_in_close (current_plug_in, TRUE);
  1568.       break;
  1569.     case GP_TEMP_PROC_RETURN:
  1570.       plug_in_handle_proc_return (msg->data);
  1571.       gtk_main_quit ();
  1572.       break;
  1573.     case GP_PROC_INSTALL:
  1574.       plug_in_handle_proc_install (msg->data);
  1575.       break;
  1576.     case GP_PROC_UNINSTALL:
  1577.       plug_in_handle_proc_uninstall (msg->data);
  1578.       break;
  1579.     case GP_EXTENSION_ACK:
  1580.       gtk_main_quit ();
  1581.       break;
  1582.     }
  1583. }
  1584.  
  1585. static void
  1586. plug_in_handle_quit (void)
  1587. {
  1588.   plug_in_close (current_plug_in, FALSE);
  1589. }
  1590.  
  1591. static void
  1592. plug_in_handle_tile_req (GPTileReq *tile_req)
  1593. {
  1594.   GPTileData   tile_data;
  1595.   GPTileData  *tile_info;
  1596.   WireMessage  msg;
  1597.   TileManager *tm;
  1598.   Tile        *tile;
  1599.  
  1600.   if (tile_req->drawable_ID == -1)
  1601.     {
  1602.       tile_data.drawable_ID = -1;
  1603.       tile_data.tile_num    = 0;
  1604.       tile_data.shadow      = 0;
  1605.       tile_data.bpp         = 0;
  1606.       tile_data.width       = 0;
  1607.       tile_data.height      = 0;
  1608.       tile_data.use_shm     = (shm_ID == -1) ? FALSE : TRUE;
  1609.       tile_data.data        = NULL;
  1610.  
  1611.       if (!gp_tile_data_write (current_writechannel, &tile_data))
  1612.     {
  1613.       g_warning ("plug_in_handle_tile_req: ERROR");
  1614.       plug_in_close (current_plug_in, TRUE);
  1615.       return;
  1616.     }
  1617.  
  1618.       if (!wire_read_msg (current_readchannel, &msg))
  1619.     {
  1620.       g_warning ("plug_in_handle_tile_req: ERROR");
  1621.       plug_in_close (current_plug_in, TRUE);
  1622.       return;
  1623.     }
  1624.  
  1625.       if (msg.type != GP_TILE_DATA)
  1626.     {
  1627.       g_warning ("expected tile data and received: %d", msg.type);
  1628.       plug_in_close (current_plug_in, TRUE);
  1629.       return;
  1630.     }
  1631.  
  1632.       tile_info = msg.data;
  1633.  
  1634.       if (tile_info->shadow)
  1635.     tm = drawable_shadow (drawable_get_ID (tile_info->drawable_ID));
  1636.       else
  1637.     tm = drawable_data (drawable_get_ID (tile_info->drawable_ID));
  1638.  
  1639.       if (!tm)
  1640.     {
  1641.       g_warning ("plug-in requested invalid drawable (killing)");
  1642.       plug_in_close (current_plug_in, TRUE);
  1643.       return;
  1644.     }
  1645.  
  1646.       tile = tile_manager_get (tm, tile_info->tile_num, TRUE, TRUE);
  1647.       if (!tile)
  1648.     {
  1649.       g_warning ("plug-in requested invalid tile (killing)");
  1650.       plug_in_close (current_plug_in, TRUE);
  1651.       return;
  1652.     }
  1653.  
  1654.       if (tile_data.use_shm)
  1655.     memcpy (tile_data_pointer (tile, 0, 0), shm_addr, tile_size (tile));
  1656.       else
  1657.     memcpy (tile_data_pointer (tile, 0, 0), tile_info->data, tile_size (tile));
  1658.  
  1659.       tile_release (tile, TRUE);
  1660.  
  1661.       wire_destroy (&msg);
  1662.       if (!gp_tile_ack_write (current_writechannel))
  1663.     {
  1664.       g_warning ("plug_in_handle_tile_req: ERROR");
  1665.       plug_in_close (current_plug_in, TRUE);
  1666.       return;
  1667.     }
  1668.     }
  1669.   else
  1670.     {
  1671.       if (tile_req->shadow)
  1672.     tm = drawable_shadow (drawable_get_ID (tile_req->drawable_ID));
  1673.       else
  1674.     tm = drawable_data (drawable_get_ID (tile_req->drawable_ID));
  1675.  
  1676.       if (!tm)
  1677.     {
  1678.       g_warning ("plug-in requested invalid drawable (killing)");
  1679.       plug_in_close (current_plug_in, TRUE);
  1680.       return;
  1681.     }
  1682.  
  1683.       tile = tile_manager_get (tm, tile_req->tile_num, TRUE, FALSE);
  1684.       if (!tile)
  1685.     {
  1686.       g_warning ("plug-in requested invalid tile (killing)");
  1687.       plug_in_close (current_plug_in, TRUE);
  1688.       return;
  1689.     }
  1690.  
  1691.       tile_data.drawable_ID = tile_req->drawable_ID;
  1692.       tile_data.tile_num    = tile_req->tile_num;
  1693.       tile_data.shadow      = tile_req->shadow;
  1694.       tile_data.bpp         = tile_bpp (tile);
  1695.       tile_data.width       = tile_ewidth (tile);
  1696.       tile_data.height      = tile_eheight (tile);
  1697.       tile_data.use_shm     = (shm_ID == -1) ? FALSE : TRUE;
  1698.  
  1699.       if (tile_data.use_shm)
  1700.     memcpy (shm_addr, tile_data_pointer (tile, 0, 0), tile_size (tile));
  1701.       else
  1702.     tile_data.data = tile_data_pointer (tile, 0, 0);
  1703.  
  1704.       if (!gp_tile_data_write (current_writechannel, &tile_data))
  1705.     {
  1706.       g_message ("plug_in_handle_tile_req: ERROR");
  1707.       plug_in_close (current_plug_in, TRUE);
  1708.       return;
  1709.     }
  1710.  
  1711.       tile_release (tile, FALSE);
  1712.  
  1713.       if (!wire_read_msg (current_readchannel, &msg))
  1714.     {
  1715.       g_message ("plug_in_handle_tile_req: ERROR");
  1716.       plug_in_close (current_plug_in, TRUE);
  1717.       return;
  1718.     }
  1719.  
  1720.       if (msg.type != GP_TILE_ACK)
  1721.     {
  1722.       g_warning ("expected tile ack and received: %d", msg.type);
  1723.       plug_in_close (current_plug_in, TRUE);
  1724.       return;
  1725.     }
  1726.  
  1727.       wire_destroy (&msg);
  1728.     }
  1729. }
  1730.  
  1731. static void
  1732. plug_in_handle_proc_run (GPProcRun *proc_run)
  1733. {
  1734.   GPProcReturn   proc_return;
  1735.   ProcRecord    *proc_rec;
  1736.   Argument      *args;
  1737.   Argument      *return_vals;
  1738.   PlugInBlocked *blocked;
  1739.  
  1740.   args = plug_in_params_to_args (proc_run->params, proc_run->nparams, FALSE);
  1741.   proc_rec = procedural_db_lookup (proc_run->name);
  1742.  
  1743.   if (proc_rec)
  1744.     {
  1745.       return_vals = procedural_db_execute (proc_run->name, args);
  1746.     }
  1747.   else
  1748.     {
  1749.       /*  if the name lookup failed, construct a 
  1750.        *  dummy "executiuon error" return value --Michael
  1751.        */
  1752.       return_vals = g_new (Argument, 1);
  1753.       return_vals[0].arg_type = PDB_STATUS;
  1754.       return_vals[0].value.pdb_int = PDB_EXECUTION_ERROR;
  1755.     }
  1756.  
  1757.   if (return_vals)
  1758.     {
  1759.       proc_return.name = proc_run->name;
  1760.  
  1761.       if (proc_rec)
  1762.     {
  1763.       proc_return.nparams = proc_rec->num_values + 1;
  1764.       proc_return.params = plug_in_args_to_params (return_vals, proc_rec->num_values + 1, FALSE);
  1765.     }
  1766.       else
  1767.     {
  1768.       proc_return.nparams = 1;
  1769.       proc_return.params = plug_in_args_to_params (return_vals, 1, FALSE);
  1770.     }
  1771.  
  1772.       if (!gp_proc_return_write (current_writechannel, &proc_return))
  1773.     {
  1774.       g_warning ("plug_in_handle_proc_run: ERROR");
  1775.       plug_in_close (current_plug_in, TRUE);
  1776.       return;
  1777.     }
  1778.  
  1779.       plug_in_args_destroy (args, proc_run->nparams, FALSE);
  1780.       plug_in_args_destroy (return_vals, (proc_rec ? (proc_rec->num_values + 1) : 1), TRUE);
  1781.       plug_in_params_destroy (proc_return.params, proc_return.nparams, FALSE);
  1782.     }
  1783.   else
  1784.     {
  1785.       blocked = g_new (PlugInBlocked, 1);
  1786.       blocked->plug_in = current_plug_in;
  1787.       blocked->proc_name = g_strdup (proc_run->name);
  1788.       blocked_plug_ins = g_slist_prepend (blocked_plug_ins, blocked);
  1789.     }
  1790. }
  1791.  
  1792. static void
  1793. plug_in_handle_proc_return (GPProcReturn *proc_return)
  1794. {
  1795.   PlugInBlocked *blocked;
  1796.   GSList        *tmp;
  1797.  
  1798.   if (current_plug_in->recurse)
  1799.     {
  1800.       current_return_vals = plug_in_params_to_args (proc_return->params,
  1801.                             proc_return->nparams,
  1802.                             TRUE);
  1803.       current_return_nvals = proc_return->nparams;
  1804.     }
  1805.   else
  1806.     {
  1807.       tmp = blocked_plug_ins;
  1808.       while (tmp)
  1809.     {
  1810.       blocked = tmp->data;
  1811.       tmp = tmp->next;
  1812.  
  1813.       if (blocked->proc_name && proc_return->name && 
  1814.           strcmp (blocked->proc_name, proc_return->name) == 0)
  1815.         {
  1816.           plug_in_push (blocked->plug_in);
  1817.           if (!gp_proc_return_write (current_writechannel, proc_return))
  1818.         {
  1819.           g_message ("plug_in_handle_proc_run: ERROR");
  1820.           plug_in_close (current_plug_in, TRUE);
  1821.           return;
  1822.         }
  1823.           plug_in_pop ();
  1824.  
  1825.           blocked_plug_ins = g_slist_remove (blocked_plug_ins, blocked);
  1826.           g_free (blocked->proc_name);
  1827.           g_free (blocked);
  1828.           break;
  1829.         }
  1830.     }
  1831.     }
  1832. }
  1833.  
  1834. static void
  1835. plug_in_handle_proc_install (GPProcInstall *proc_install)
  1836. {
  1837.   PlugInDef       *plug_in_def = NULL;
  1838.   PlugInProcDef   *proc_def;
  1839.   ProcRecord      *proc = NULL;
  1840.   PlugInMenuEntry *menu_entry;
  1841.   GSList          *tmp = NULL;
  1842.   gchar           *prog = NULL;
  1843.   gboolean         add_proc_def;
  1844.   gint i;
  1845.  
  1846.   /*  Argument checking
  1847.    *   --only sanity check arguments when the procedure requests a menu path
  1848.    */
  1849.  
  1850.   if (proc_install->menu_path)
  1851.     {
  1852.       if (strchr (proc_install->menu_path, '_'))
  1853.     {
  1854.       g_message ("Plug-In \"%s\" (%s)\n"
  1855.              "attempted to install procedure \"%s\"\n"
  1856.              "with a menu path that contains an underscore. "
  1857.              "This is not supported.",
  1858.              g_basename (current_plug_in->args[0]),
  1859.              current_plug_in->args[0],
  1860.              proc_install->name);
  1861.       return;
  1862.     }
  1863.  
  1864.       if (strncmp (proc_install->menu_path, "<Toolbox>", 9) == 0)
  1865.     {
  1866.       if ((proc_install->nparams < 1) ||
  1867.           (proc_install->params[0].type != PDB_INT32))
  1868.         {
  1869.           g_message ("Plug-In \"%s\" (%s)\n"
  1870.              "attempted to install procedure \"%s\"\n"
  1871.              "which does not take the standard Plug-In args.",
  1872.              g_basename (current_plug_in->args[0]),
  1873.              current_plug_in->args[0],
  1874.              proc_install->name);
  1875.           return;
  1876.         }
  1877.     }
  1878.       else if (strncmp (proc_install->menu_path, "<Image>", 7) == 0)
  1879.     {
  1880.       if ((proc_install->nparams < 3) ||
  1881.           (proc_install->params[0].type != PDB_INT32) ||
  1882.           (proc_install->params[1].type != PDB_IMAGE) ||
  1883.           (proc_install->params[2].type != PDB_DRAWABLE))
  1884.         {
  1885.           g_message ("Plug-In \"%s\" (%s)\n"
  1886.              "attempted to install procedure \"%s\"\n"
  1887.              "which does not take the standard Plug-In args.",
  1888.              g_basename (current_plug_in->args[0]),
  1889.              current_plug_in->args[0],
  1890.              proc_install->name);
  1891.           return;
  1892.         }
  1893.     }
  1894.       else if (strncmp (proc_install->menu_path, "<Load>", 6) == 0)
  1895.     {
  1896.       if ((proc_install->nparams < 3) ||
  1897.           (proc_install->params[0].type != PDB_INT32) ||
  1898.           (proc_install->params[1].type != PDB_STRING) ||
  1899.           (proc_install->params[2].type != PDB_STRING))
  1900.         {
  1901.           g_message ("Plug-In \"%s\" (%s)\n"
  1902.              "attempted to install procedure \"%s\"\n"
  1903.              "which does not take the standard Plug-In args.",
  1904.              g_basename (current_plug_in->args[0]),
  1905.              current_plug_in->args[0],
  1906.              proc_install->name);
  1907.           return;
  1908.         }
  1909.     }
  1910.       else if (strncmp (proc_install->menu_path, "<Save>", 6) == 0)
  1911.     {
  1912.       if ((proc_install->nparams < 5) ||
  1913.           (proc_install->params[0].type != PDB_INT32) ||
  1914.           (proc_install->params[1].type != PDB_IMAGE) ||
  1915.           (proc_install->params[2].type != PDB_DRAWABLE) ||
  1916.           (proc_install->params[3].type != PDB_STRING) ||
  1917.           (proc_install->params[4].type != PDB_STRING))
  1918.         {
  1919.           g_message ("Plug-In \"%s\" (%s)\n"
  1920.              "attempted to install procedure \"%s\"\n"
  1921.              "which does not take the standard Plug-In args.",
  1922.              g_basename (current_plug_in->args[0]),
  1923.              current_plug_in->args[0],
  1924.              proc_install->name);
  1925.           return;
  1926.         }
  1927.     }
  1928.       else
  1929.     {
  1930.       g_message ("Plug-In \"%s\" (%s)\n"
  1931.              "attempted to install procedure \"%s\"\n"
  1932.              "in an invalid menu location.\n"
  1933.              "Use either \"<Toolbox>\", \"<Image>\", "
  1934.              "\"<Load>\", or \"<Save>\".",
  1935.              g_basename (current_plug_in->args[0]),
  1936.              current_plug_in->args[0],
  1937.              proc_install->name);
  1938.       return;
  1939.     }
  1940.     }
  1941.  
  1942.   /*  Sanity check for array arguments  */
  1943.  
  1944.   for (i = 1; i < proc_install->nparams; i++) 
  1945.     {
  1946.       if ((proc_install->params[i].type == PDB_INT32ARRAY ||
  1947.        proc_install->params[i].type == PDB_INT8ARRAY ||
  1948.        proc_install->params[i].type == PDB_FLOATARRAY ||
  1949.        proc_install->params[i].type == PDB_STRINGARRAY) &&
  1950.       proc_install->params[i-1].type != PDB_INT32) 
  1951.     {
  1952.       g_message ("Plug-In \"%s\"\n(%s)\n"
  1953.              "attempted to install procedure \"%s\"\n"
  1954.              "which fails to comply with the array parameter\n"
  1955.              "passing standard.  Argument %d is noncompliant.", 
  1956.              g_basename (current_plug_in->args[0]),
  1957.              current_plug_in->args[0],
  1958.              proc_install->name, i);
  1959.       return;
  1960.     }
  1961.     }
  1962.   
  1963.  
  1964.   /*  Initialization  */
  1965.  
  1966.   proc_def = NULL;
  1967.  
  1968.   switch (proc_install->type)
  1969.     {
  1970.     case PDB_PLUGIN:
  1971.     case PDB_EXTENSION:
  1972.       plug_in_def = current_plug_in->user_data;
  1973.       prog = plug_in_def->prog;
  1974.  
  1975.       tmp = plug_in_def->proc_defs;
  1976.       break;
  1977.  
  1978.     case PDB_TEMPORARY:
  1979.       prog = "none";
  1980.  
  1981.       tmp = current_plug_in->temp_proc_defs;
  1982.       break;
  1983.     }
  1984.  
  1985. #ifdef HACK_FOR_BUG_66859
  1986.   /* Is the plug-in only telling us that it has an init_proc? */
  1987.   if (strcmp (proc_install->name, GIMP_HAVE_INIT_PROC_MARKER) == 0)
  1988.     {
  1989.       plug_in_def->init = TRUE;
  1990.       return;
  1991.     }
  1992. #endif
  1993.  
  1994.   while (tmp)
  1995.     {
  1996.       proc_def = tmp->data;
  1997.       tmp = tmp->next;
  1998.  
  1999.       if (strcmp (proc_def->db_info.name, proc_install->name) == 0)
  2000.     {
  2001.       if (proc_install->type == PDB_TEMPORARY)
  2002.         plug_in_proc_def_remove (proc_def);
  2003.       else
  2004.         plug_in_proc_def_destroy (proc_def, TRUE);  /* destroys data_only */ 
  2005.  
  2006.       break;
  2007.     }
  2008.  
  2009.       proc_def = NULL;
  2010.     }
  2011.  
  2012.   add_proc_def = FALSE;
  2013.   if (!proc_def)
  2014.     {
  2015.       add_proc_def = TRUE;
  2016.       proc_def = g_new (PlugInProcDef, 1);
  2017.     }
  2018.  
  2019.   proc_def->prog = g_strdup (prog);
  2020.  
  2021.   proc_def->menu_path       = g_strdup (proc_install->menu_path);
  2022.   proc_def->accelerator     = NULL;
  2023.   proc_def->extensions      = NULL;
  2024.   proc_def->prefixes        = NULL;
  2025.   proc_def->magics          = NULL;
  2026.   proc_def->image_types     = g_strdup (proc_install->image_types);
  2027.   proc_def->image_types_val = plug_in_image_types_parse (proc_def->image_types);
  2028.   /* Install temp one use todays time */
  2029.   proc_def->mtime           = time (NULL);
  2030.  
  2031.   proc = &proc_def->db_info;
  2032.  
  2033.   /*  The procedural database procedure  */
  2034.  
  2035.   proc->name      = g_strdup (proc_install->name);
  2036.   proc->blurb     = g_strdup (proc_install->blurb);
  2037.   proc->help      = g_strdup (proc_install->help);
  2038.   proc->author    = g_strdup (proc_install->author);
  2039.   proc->copyright = g_strdup (proc_install->copyright);
  2040.   proc->date      = g_strdup (proc_install->date);
  2041.   proc->proc_type = proc_install->type;
  2042.  
  2043.   proc->num_args   = proc_install->nparams;
  2044.   proc->num_values = proc_install->nreturn_vals;
  2045.  
  2046.   proc->args   = g_new (ProcArg, proc->num_args);
  2047.   proc->values = g_new (ProcArg, proc->num_values);
  2048.  
  2049.   for (i = 0; i < proc->num_args; i++)
  2050.     {
  2051.       proc->args[i].arg_type    = proc_install->params[i].type;
  2052.       proc->args[i].name        = g_strdup (proc_install->params[i].name);
  2053.       proc->args[i].description = g_strdup (proc_install->params[i].description);
  2054.     }
  2055.  
  2056.   for (i = 0; i < proc->num_values; i++)
  2057.     {
  2058.       proc->values[i].arg_type    = proc_install->return_vals[i].type;
  2059.       proc->values[i].name        = g_strdup (proc_install->return_vals[i].name);
  2060.       proc->values[i].description = g_strdup (proc_install->return_vals[i].description);
  2061.     }
  2062.  
  2063.   switch (proc_install->type)
  2064.     {
  2065.     case PDB_PLUGIN:
  2066.     case PDB_EXTENSION:
  2067.       if (add_proc_def)
  2068.     plug_in_def->proc_defs = g_slist_prepend (plug_in_def->proc_defs, proc_def);
  2069.       break;
  2070.  
  2071.     case PDB_TEMPORARY:
  2072.       if (add_proc_def)
  2073.     current_plug_in->temp_proc_defs = 
  2074.       g_slist_prepend (current_plug_in->temp_proc_defs, proc_def);
  2075.  
  2076.       proc_defs = g_slist_append (proc_defs, proc_def);
  2077.       proc->exec_method.temporary.plug_in = (void *) current_plug_in;
  2078.       procedural_db_register (proc);
  2079.  
  2080.       /*  If there is a menu path specified, create a menu entry  */
  2081.       if (proc_install->menu_path)
  2082.     {
  2083.       menu_entry = g_new (PlugInMenuEntry, 1);
  2084.       menu_entry->proc_def = proc_def;
  2085.  
  2086.       /*  Below we use a hack to allow translations of Script-Fu paths.
  2087.            *  Would be nice if we could solve this properly, but I haven't 
  2088.            *  found a way yet ...  (Sven)
  2089.        */
  2090.       if (plug_in_def && plug_in_def->locale_domain)
  2091.         menu_entry->domain = plug_in_def->locale_domain;
  2092.       else if (strncmp (proc_def->db_info.name, "script_fu", 9) == 0)
  2093.         menu_entry->domain = "gimp-script-fu";
  2094.       else
  2095.         menu_entry->domain = std_plugins_domain;
  2096.  
  2097.       if (plug_in_def)
  2098.         menu_entry->help_path = plug_in_def->help_path;
  2099.       else
  2100.         menu_entry->help_path = NULL;
  2101.  
  2102.       /* plug_in_make_menu_entry frees the menu_entry for us */
  2103.       plug_in_make_menu_entry (NULL, menu_entry, NULL);  
  2104.     }
  2105.       break;
  2106.     }
  2107. }
  2108.  
  2109. static void
  2110. plug_in_handle_proc_uninstall (GPProcUninstall *proc_uninstall)
  2111. {
  2112.   PlugInProcDef *proc_def;
  2113.   GSList        *tmp;
  2114.  
  2115.   tmp = current_plug_in->temp_proc_defs;
  2116.   while (tmp)
  2117.     {
  2118.       proc_def = tmp->data;
  2119.       tmp = tmp->next;
  2120.  
  2121.       if (strcmp (proc_def->db_info.name, proc_uninstall->name) == 0)
  2122.     {
  2123.       current_plug_in->temp_proc_defs = g_slist_remove (current_plug_in->temp_proc_defs, proc_def);
  2124.       plug_in_proc_def_remove (proc_def);
  2125.       break;
  2126.     }
  2127.     }
  2128. }
  2129.  
  2130. static gboolean
  2131. plug_in_write (GIOChannel *channel,
  2132.            guint8      *buf,
  2133.            gulong       count)
  2134. {
  2135.   gulong bytes;
  2136.  
  2137.   while (count > 0)
  2138.     {
  2139.       if ((current_write_buffer_index + count) >= WRITE_BUFFER_SIZE)
  2140.     {
  2141.       bytes = WRITE_BUFFER_SIZE - current_write_buffer_index;
  2142.       memcpy (¤t_write_buffer[current_write_buffer_index], buf, bytes);
  2143.       current_write_buffer_index += bytes;
  2144.       if (!wire_flush (channel))
  2145.         return FALSE;
  2146.     }
  2147.       else
  2148.     {
  2149.       bytes = count;
  2150.       memcpy (¤t_write_buffer[current_write_buffer_index], buf, bytes);
  2151.       current_write_buffer_index += bytes;
  2152.     }
  2153.  
  2154.       buf += bytes;
  2155.       count -= bytes;
  2156.     }
  2157.  
  2158.   return TRUE;
  2159. }
  2160.  
  2161. static gboolean
  2162. plug_in_flush (GIOChannel *channel)
  2163. {
  2164.   GIOError error;
  2165.   gint     count;
  2166.   guint    bytes;
  2167.  
  2168.   if (current_write_buffer_index > 0)
  2169.     {
  2170.       count = 0;
  2171.       while (count != current_write_buffer_index)
  2172.         {
  2173.       do {
  2174.         bytes = 0;
  2175.         error = g_io_channel_write (channel, ¤t_write_buffer[count],
  2176.                     (current_write_buffer_index - count),
  2177.                     &bytes);
  2178.       } while (error == G_IO_ERROR_AGAIN);
  2179.  
  2180.       if (error != G_IO_ERROR_NONE)
  2181.         return FALSE;
  2182.  
  2183.           count += bytes;
  2184.         }
  2185.  
  2186.       current_write_buffer_index = 0;
  2187.     }
  2188.  
  2189.   return TRUE;
  2190. }
  2191.  
  2192. static void
  2193. plug_in_push (PlugIn *plug_in)
  2194. {
  2195.   if (plug_in)
  2196.     {
  2197.       current_plug_in = plug_in;
  2198.       plug_in_stack = g_slist_prepend (plug_in_stack, current_plug_in);
  2199.  
  2200.       current_readchannel        = current_plug_in->my_read;
  2201.       current_writechannel       = current_plug_in->my_write;
  2202.       current_write_buffer_index = current_plug_in->write_buffer_index;
  2203.       current_write_buffer       = current_plug_in->write_buffer;
  2204.     }
  2205.   else
  2206.     {
  2207.       current_readchannel        = NULL;
  2208.       current_writechannel       = NULL;
  2209.       current_write_buffer_index = 0;
  2210.       current_write_buffer       = NULL;
  2211.     }
  2212. }
  2213.  
  2214. static void
  2215. plug_in_pop (void)
  2216. {
  2217.   GSList *tmp;
  2218.  
  2219.   if (current_plug_in)
  2220.     {
  2221.       current_plug_in->write_buffer_index = current_write_buffer_index;
  2222.  
  2223.       tmp = plug_in_stack;
  2224.       plug_in_stack = plug_in_stack->next;
  2225.       tmp->next = NULL;
  2226.       g_slist_free (tmp);
  2227.     }
  2228.  
  2229.   if (plug_in_stack)
  2230.     {
  2231.       current_plug_in            = plug_in_stack->data;
  2232.       current_readchannel        = current_plug_in->my_read;
  2233.       current_writechannel       = current_plug_in->my_write;
  2234.       current_write_buffer_index = current_plug_in->write_buffer_index;
  2235.       current_write_buffer       = current_plug_in->write_buffer;
  2236.     }
  2237.   else
  2238.     {
  2239.       current_plug_in            = NULL;
  2240.       current_readchannel        = NULL;
  2241.       current_writechannel       = NULL;
  2242.       current_write_buffer_index = 0;
  2243.       current_write_buffer        = NULL;
  2244.     }
  2245. }
  2246.  
  2247. static void
  2248. plug_in_write_rc_string (FILE  *fp,
  2249.              gchar *str)
  2250. {
  2251.   fputc ('"', fp);
  2252.  
  2253.   if (str)
  2254.     while (*str)
  2255.       {
  2256.     if (*str == '\n')
  2257.       {
  2258.         fputc ('\\', fp);
  2259.         fputc ('n', fp);
  2260.       }
  2261.     else if (*str == '\r')
  2262.       {
  2263.         fputc ('\\', fp);
  2264.         fputc ('r', fp);
  2265.       }
  2266.     else if (*str == '\032') /* ^Z is problematic on Windows */
  2267.       {
  2268.         fputc ('\\', fp);
  2269.         fputc ('z', fp);
  2270.       }
  2271.     else
  2272.       {
  2273.         if ((*str == '"') || (*str == '\\'))
  2274.           fputc ('\\', fp);
  2275.         fputc (*str, fp);
  2276.       }
  2277.     str += 1;
  2278.       }
  2279.  
  2280.   fputc ('"', fp);
  2281. }
  2282.  
  2283. static void
  2284. plug_in_write_rc (gchar *filename)
  2285. {
  2286.   FILE          *fp;
  2287.   PlugInDef     *plug_in_def;
  2288.   PlugInProcDef *proc_def;
  2289.   GSList        *tmp;
  2290.   GSList        *tmp2;
  2291.   gint i;
  2292.  
  2293.   fp = fopen (filename, "w");
  2294.   if (!fp)
  2295.     return;
  2296.  
  2297.   tmp = plug_in_defs;
  2298.   while (tmp)
  2299.     {
  2300.       plug_in_def = tmp->data;
  2301.       tmp = tmp->next;
  2302.  
  2303.       if (plug_in_def->proc_defs)
  2304.     {
  2305.       fprintf (fp, "(plug-in-def ");
  2306.       plug_in_write_rc_string (fp, plug_in_def->prog);
  2307.       fprintf (fp, " %ld", (long) plug_in_def->mtime);
  2308.       tmp2 = plug_in_def->proc_defs;
  2309.       if (tmp2)
  2310.         fprintf (fp, "\n");
  2311.  
  2312.       while (tmp2)
  2313.         {
  2314.           proc_def = tmp2->data;
  2315.           tmp2 = tmp2->next;
  2316.  
  2317.           fprintf (fp, "\t(proc-def \"%s\" %d\n",
  2318.                proc_def->db_info.name, proc_def->db_info.proc_type);
  2319.           fprintf (fp, "\t\t");
  2320.           plug_in_write_rc_string (fp, proc_def->db_info.blurb);
  2321.           fprintf (fp, "\n\t\t");
  2322.           plug_in_write_rc_string (fp, proc_def->db_info.help);
  2323.           fprintf (fp, "\n\t\t");
  2324.           plug_in_write_rc_string (fp, proc_def->db_info.author);
  2325.           fprintf (fp, "\n\t\t");
  2326.           plug_in_write_rc_string (fp, proc_def->db_info.copyright);
  2327.           fprintf (fp, "\n\t\t");
  2328.           plug_in_write_rc_string (fp, proc_def->db_info.date);
  2329.           fprintf (fp, "\n\t\t");
  2330.           plug_in_write_rc_string (fp, proc_def->menu_path);
  2331.           fprintf (fp, "\n\t\t");
  2332.           plug_in_write_rc_string (fp, proc_def->extensions);
  2333.           fprintf (fp, "\n\t\t");
  2334.           plug_in_write_rc_string (fp, proc_def->prefixes);
  2335.           fprintf (fp, "\n\t\t");
  2336.           plug_in_write_rc_string (fp, proc_def->magics);
  2337.           fprintf (fp, "\n\t\t");
  2338.           plug_in_write_rc_string (fp, proc_def->image_types);
  2339.           fprintf (fp, "\n\t\t%d %d\n",
  2340.                proc_def->db_info.num_args, proc_def->db_info.num_values);
  2341.  
  2342.           for (i = 0; i < proc_def->db_info.num_args; i++)
  2343.         {
  2344.           fprintf (fp, "\t\t(proc-arg %d ",
  2345.                proc_def->db_info.args[i].arg_type);
  2346.  
  2347.           plug_in_write_rc_string (fp, proc_def->db_info.args[i].name);
  2348.           plug_in_write_rc_string (fp, proc_def->db_info.args[i].description);
  2349.  
  2350.           fprintf (fp, ")%s",
  2351.                (proc_def->db_info.num_values ||
  2352.                 (i < (proc_def->db_info.num_args - 1))) ? "\n" : "");
  2353.         }
  2354.  
  2355.           for (i = 0; i < proc_def->db_info.num_values; i++)
  2356.         {
  2357.           fprintf (fp, "\t\t(proc-arg %d ",
  2358.                proc_def->db_info.values[i].arg_type);
  2359.  
  2360.           plug_in_write_rc_string (fp, proc_def->db_info.values[i].name);
  2361.           plug_in_write_rc_string (fp, proc_def->db_info.values[i].description);
  2362.  
  2363.           fprintf (fp, ")%s", (i < (proc_def->db_info.num_values - 1)) ? "\n" : "");
  2364.         }
  2365.  
  2366.           fprintf (fp, ")");
  2367.  
  2368.           if (tmp2)
  2369.         fprintf (fp, "\n");
  2370.         }
  2371.       
  2372.       if (plug_in_def->locale_domain)
  2373.         {
  2374.           fprintf (fp, "\n\t(locale-def \"%s\"", plug_in_def->locale_domain);
  2375.           if (plug_in_def->locale_path)
  2376.         fprintf (fp, " \"%s\")", plug_in_def->locale_path);
  2377.           else
  2378.         fprintf (fp, ")");
  2379.         }
  2380.  
  2381.       if (plug_in_def->help_path)
  2382.         {
  2383.           fprintf (fp, "\n\t(help-def \"%s\")", plug_in_def->help_path);
  2384.         }
  2385.  
  2386. #ifdef HACK_FOR_BUG_66859
  2387.       if (plug_in_def->init)
  2388.         {
  2389.           fprintf (fp, "\n\t(has-init)");
  2390.         }
  2391. #endif
  2392.       fprintf (fp, ")\n");
  2393.  
  2394.       if (tmp)
  2395.         fprintf (fp, "\n");
  2396.     }
  2397.       
  2398.     }
  2399.  
  2400.   fclose (fp);
  2401. }
  2402.  
  2403. static void
  2404. plug_in_init_file (gchar *filename)
  2405. {
  2406.   GSList    *tmp;
  2407.   PlugInDef *plug_in_def;
  2408.   gchar     *plug_in_name;
  2409.   gchar     *name;
  2410.  
  2411.   name = g_basename (filename);
  2412.  
  2413.   plug_in_def = NULL;
  2414.   tmp = plug_in_defs;
  2415.  
  2416.   while (tmp)
  2417.     {
  2418.       plug_in_def = tmp->data;
  2419.       tmp = tmp->next;
  2420.  
  2421.       plug_in_name = g_basename (plug_in_def->prog);
  2422.  
  2423.       if (g_strcasecmp (name, plug_in_name) == 0)
  2424.     {
  2425.       g_print ("duplicate plug-in: \"%s\" (skipping)\n", filename);
  2426.       return;
  2427.     }
  2428.  
  2429.       plug_in_def = NULL;
  2430.     }
  2431.  
  2432.   plug_in_def = plug_in_def_new (filename);
  2433.   plug_in_def->mtime = datafile_mtime ();
  2434.   plug_in_def->query = TRUE;
  2435.  
  2436.   plug_in_defs = g_slist_append (plug_in_defs, plug_in_def);
  2437. }
  2438.  
  2439. static void
  2440. plug_in_query (PlugInDef *plug_in_def)
  2441. {
  2442.   PlugIn      *plug_in;
  2443.   WireMessage  msg;
  2444.  
  2445.   plug_in = plug_in_new (plug_in_def->prog);
  2446.   if (plug_in)
  2447.     {
  2448.       plug_in->query       = TRUE;
  2449.       plug_in->synchronous = TRUE;
  2450.       plug_in->user_data   = plug_in_def;
  2451.  
  2452.       if (plug_in_open (plug_in))
  2453.     {
  2454.       plug_in_push (plug_in);
  2455.  
  2456.       while (plug_in->open)
  2457.         {
  2458.           if (!wire_read_msg (current_readchannel, &msg))
  2459.         plug_in_close (current_plug_in, TRUE);
  2460.           else 
  2461.         {
  2462.           plug_in_handle_message (&msg);
  2463.           wire_destroy (&msg);
  2464.         }
  2465.         }
  2466.  
  2467.       plug_in_pop ();
  2468.       plug_in_destroy (plug_in);
  2469.     }
  2470.     }
  2471. }
  2472.  
  2473. #ifdef HACK_FOR_BUG_66859
  2474.  
  2475. static void
  2476. plug_in_initialize (PlugInDef *plug_in_def)
  2477. {
  2478.   PlugIn      *plug_in;
  2479.   WireMessage  msg;
  2480.  
  2481.   plug_in = plug_in_new (plug_in_def->prog);
  2482.   if (plug_in)
  2483.     {
  2484.       plug_in->init        = TRUE;
  2485.       plug_in->synchronous = TRUE;
  2486.       plug_in->user_data   = plug_in_def;
  2487.  
  2488.       if (plug_in_open (plug_in))
  2489.     {
  2490.       plug_in_push (plug_in);
  2491.  
  2492.       while (plug_in->open)
  2493.         {
  2494.           if (!wire_read_msg (current_readchannel, &msg))
  2495.         plug_in_close (current_plug_in, TRUE);
  2496.           else 
  2497.         {
  2498.           plug_in_handle_message (&msg);
  2499.           wire_destroy (&msg);
  2500.         }
  2501.         }
  2502.  
  2503.       plug_in_pop ();
  2504.       plug_in_destroy (plug_in);
  2505.     }
  2506.     }
  2507. }
  2508.  
  2509. #endif
  2510.  
  2511. static void
  2512. plug_in_add_to_db (void)
  2513. {
  2514.   PlugInProcDef *proc_def;
  2515.   Argument       args[4];
  2516.   Argument      *return_vals;
  2517.   GSList        *tmp;
  2518.  
  2519.   tmp = proc_defs;
  2520.  
  2521.   while (tmp)
  2522.     {
  2523.       proc_def = tmp->data;
  2524.       tmp = tmp->next;
  2525.  
  2526.       if (proc_def->prog && (proc_def->db_info.proc_type != PDB_INTERNAL))
  2527.     {
  2528.       proc_def->db_info.exec_method.plug_in.filename = proc_def->prog;
  2529.       procedural_db_register (&proc_def->db_info);
  2530.     }
  2531.     }
  2532.  
  2533.   for (tmp = proc_defs; tmp; tmp = tmp->next)
  2534.     {
  2535.       proc_def = tmp->data;
  2536.  
  2537.       if (proc_def->extensions || proc_def->prefixes || proc_def->magics)
  2538.         {
  2539.           args[0].arg_type          = PDB_STRING;
  2540.           args[0].value.pdb_pointer = proc_def->db_info.name;
  2541.  
  2542.           args[1].arg_type          = PDB_STRING;
  2543.           args[1].value.pdb_pointer = proc_def->extensions;
  2544.  
  2545.       args[2].arg_type          = PDB_STRING;
  2546.       args[2].value.pdb_pointer = proc_def->prefixes;
  2547.  
  2548.       args[3].arg_type          = PDB_STRING;
  2549.       args[3].value.pdb_pointer = proc_def->magics;
  2550.  
  2551.           if (proc_def->image_types)
  2552.             {
  2553.               return_vals = procedural_db_execute ("gimp_register_save_handler", args);
  2554.               g_free (return_vals);
  2555.             }
  2556.           else
  2557.             {
  2558.               return_vals = procedural_db_execute ("gimp_register_magic_load_handler", args);
  2559.               g_free (return_vals);
  2560.             }
  2561.     }
  2562.     }
  2563. }
  2564.  
  2565. /*  The following function has to be a GTraverseFunction, 
  2566.  *  but is also called directly. Please note that it frees the
  2567.  *  menu_entry strcuture.                --Sven 
  2568.  */ 
  2569. static gint
  2570. plug_in_make_menu_entry (gpointer         foo,
  2571.              PlugInMenuEntry *menu_entry,
  2572.              gpointer         bar)
  2573. {
  2574.   GimpItemFactoryEntry  entry;
  2575.   gchar                *help_page;
  2576.   
  2577.   if (menu_entry->help_path)
  2578.     {
  2579.       help_page = g_strconcat (menu_entry->help_path,
  2580.                    "@",   /* HACK: locale subdir */
  2581.                    g_basename (menu_entry->proc_def->prog),
  2582.                    ".html",
  2583.                    NULL);
  2584.     }
  2585.   else
  2586.     {
  2587.       help_page = g_strconcat ("filters/",  /* _not_ G_DIR_SEPARATOR_S */
  2588.                    g_basename (menu_entry->proc_def->prog),
  2589.                    ".html",
  2590.                    NULL);
  2591.     }
  2592.  
  2593.   g_strdown (help_page);
  2594.   
  2595.   entry.entry.path            = menu_entry->proc_def->menu_path;
  2596.   entry.entry.accelerator     = menu_entry->proc_def->accelerator;
  2597.   entry.entry.callback        = plug_in_callback;
  2598.   entry.entry.callback_action = 0;
  2599.   entry.entry.item_type       = NULL;
  2600.   entry.help_page             = help_page;
  2601.   entry.description           = NULL;
  2602.  
  2603.   menus_create_item_from_full_path (&entry, 
  2604.                     menu_entry->domain, 
  2605.                     &menu_entry->proc_def->db_info);
  2606.   g_free (menu_entry);
  2607.   
  2608.   return FALSE;
  2609. }
  2610.  
  2611. static void
  2612. plug_in_make_menu (void)
  2613. {
  2614.   PlugInDef       *plug_in_def;
  2615.   PlugInProcDef   *proc_def;
  2616.   PlugInMenuEntry *menu_entry;
  2617.   GSList *domains = NULL;
  2618.   GSList *procs;
  2619.   GSList *tmp;
  2620.   GTree  *menu_entries;
  2621.  
  2622. #ifdef ENABLE_NLS
  2623.   bindtextdomain (std_plugins_domain, LOCALEDIR);
  2624. #if defined (HAVE_BIND_TEXTDOMAIN_CODESET) && defined (GDK_WINDOWING_WIN32)
  2625.   bind_textdomain_codeset (std_plugins_domain, "UTF-8");
  2626. #endif
  2627.   domains = g_slist_append (domains, std_plugins_domain);
  2628. #endif
  2629.  
  2630. #ifdef ENABLE_NLS
  2631.   menu_entries = g_tree_new ((GCompareFunc)strcoll);
  2632. #else
  2633.   menu_entries = g_tree_new ((GCompareFunc)strcmp);
  2634. #endif
  2635.  
  2636.   tmp = plug_in_defs;
  2637.   while (tmp)
  2638.     {
  2639.       plug_in_def = tmp->data;
  2640.       tmp = tmp->next;
  2641.  
  2642.       procs = plug_in_def->proc_defs;
  2643.  
  2644.       if (!procs)
  2645.     continue;
  2646.  
  2647. #ifdef ENABLE_NLS
  2648.       {
  2649.     gchar    *domain;
  2650.     GSList   *list;
  2651.     gboolean  found = FALSE;
  2652.  
  2653.     if (plug_in_def->locale_domain)
  2654.       {
  2655.         domain = plug_in_def->locale_domain;
  2656.         for (list = domains; list && !found; list = list->next)
  2657.           {
  2658.         if (strcmp (domain, (gchar*)(list->data)) == 0)
  2659.           found = TRUE;
  2660.           }
  2661.         if (!found)
  2662.           {
  2663.         domains = g_slist_append (domains, domain);
  2664.         if (plug_in_def->locale_path)
  2665.           bindtextdomain (domain, plug_in_def->locale_path);
  2666.         else
  2667.           bindtextdomain (domain, LOCALEDIR);
  2668. #if defined (HAVE_BIND_TEXTDOMAIN_CODESET) && defined (GDK_WINDOWING_WIN32)
  2669.         bind_textdomain_codeset (domain, "UTF-8");
  2670. #endif
  2671.           }
  2672.       }
  2673.       }
  2674. #endif  /*  ENABLE_NLS  */
  2675.  
  2676.       while (procs)
  2677.     {
  2678.       proc_def = procs->data;
  2679.       procs = procs->next;
  2680.  
  2681.       if (proc_def->prog && proc_def->menu_path && (!proc_def->extensions &&
  2682.                             !proc_def->prefixes &&
  2683.                             !proc_def->magics))
  2684.         {
  2685.           menu_entry = g_new (PlugInMenuEntry, 1);
  2686.           menu_entry->proc_def = proc_def;
  2687.           menu_entry->domain   = plug_in_def->locale_domain ? 
  2688.         plug_in_def->locale_domain : std_plugins_domain;
  2689.           menu_entry->help_path = plug_in_def->help_path;
  2690.  
  2691.           g_tree_insert (menu_entries, 
  2692.                  dgettext (menu_entry->domain, proc_def->menu_path),
  2693.                  menu_entry);
  2694.         }
  2695.     }
  2696.     }
  2697.  
  2698.   g_tree_traverse (menu_entries, 
  2699.            (GTraverseFunc)plug_in_make_menu_entry, G_IN_ORDER, NULL);
  2700.   g_tree_destroy (menu_entries);
  2701.  
  2702.   g_slist_free (domains);
  2703. }
  2704.  
  2705.  
  2706. static void
  2707. plug_in_callback (GtkWidget *widget,
  2708.           gpointer   client_data)
  2709. {
  2710.   GDisplay   *gdisplay;
  2711.   ProcRecord *proc_rec;
  2712.   Argument   *args;
  2713.   gint i;
  2714.   gint gdisp_ID = -1;
  2715.   gint argc = 0; /* calm down a gcc warning.  */
  2716.  
  2717.   /* get the active gdisplay */
  2718.   gdisplay = gdisplay_active ();
  2719.  
  2720.   proc_rec = (ProcRecord *) client_data;
  2721.  
  2722.   /* construct the procedures arguments */
  2723.   args = g_new0 (Argument, proc_rec->num_args);
  2724.  
  2725.   /* initialize the argument types */
  2726.   for (i = 0; i < proc_rec->num_args; i++)
  2727.     args[i].arg_type = proc_rec->args[i].arg_type;
  2728.  
  2729.   switch (proc_rec->proc_type)
  2730.     {
  2731.     case PDB_EXTENSION:
  2732.       /* initialize the first argument  */
  2733.       args[0].value.pdb_int = RUN_INTERACTIVE;
  2734.       argc = 1;
  2735.       break;
  2736.  
  2737.     case PDB_PLUGIN:
  2738.       if (gdisplay)
  2739.     {
  2740.       gdisp_ID = gdisplay->ID;
  2741.  
  2742.       /* initialize the first 3 plug-in arguments  */
  2743.       args[0].value.pdb_int = RUN_INTERACTIVE;
  2744.       args[1].value.pdb_int = pdb_image_to_id (gdisplay->gimage);
  2745.       args[2].value.pdb_int = drawable_ID (gimage_active_drawable (gdisplay->gimage));
  2746.       argc = 3;
  2747.     }
  2748.       else
  2749.     {
  2750.       g_warning ("Uh-oh, no active gdisplay for the plug-in!");
  2751.       g_free (args);
  2752.       return;
  2753.     }
  2754.       break;
  2755.  
  2756.     case PDB_TEMPORARY:
  2757.       args[0].value.pdb_int = RUN_INTERACTIVE;
  2758.       argc = 1;
  2759.       if (proc_rec->num_args >= 3 &&
  2760.       proc_rec->args[1].arg_type == PDB_IMAGE &&
  2761.       proc_rec->args[2].arg_type == PDB_DRAWABLE)
  2762.     {
  2763.       if (gdisplay)
  2764.         {
  2765.           gdisp_ID = gdisplay->ID;
  2766.  
  2767.           args[1].value.pdb_int = pdb_image_to_id (gdisplay->gimage);
  2768.           args[2].value.pdb_int = drawable_ID (gimage_active_drawable (gdisplay->gimage));
  2769.           argc = 3;
  2770.         }
  2771.       else
  2772.         {
  2773.           g_warning ("Uh-oh, no active gdisplay for the temporary procedure!");
  2774.           g_free (args);
  2775.           return;
  2776.         }
  2777.     }
  2778.       break;
  2779.  
  2780.     default:
  2781.       g_error ("Unknown procedure type.");
  2782.       g_free (args);
  2783.       return;
  2784.     }
  2785.  
  2786.   /* run the plug-in procedure */
  2787.   plug_in_run (proc_rec, args, argc, FALSE, TRUE, gdisp_ID);
  2788.  
  2789.   if (proc_rec->proc_type == PDB_PLUGIN)
  2790.     last_plug_in = proc_rec;
  2791.  
  2792.   g_free (args);
  2793. }
  2794.  
  2795. static void
  2796. plug_in_proc_def_insert (PlugInProcDef *proc_def,
  2797.              void (*superceed_fn)(void*))
  2798. {
  2799.   PlugInProcDef *tmp_proc_def;
  2800.   GSList *tmp;
  2801.   GSList *prev;
  2802.   GSList *list;
  2803.  
  2804.   prev = NULL;
  2805.   tmp  = proc_defs;
  2806.  
  2807.   while (tmp)
  2808.     {
  2809.       tmp_proc_def = tmp->data;
  2810.  
  2811.       if (strcmp (proc_def->db_info.name, tmp_proc_def->db_info.name) == 0)
  2812.     {
  2813.       tmp->data = proc_def;
  2814.  
  2815.       if (proc_def->menu_path)
  2816.         g_free (proc_def->menu_path);
  2817.       if (proc_def->accelerator)
  2818.         g_free (proc_def->accelerator);
  2819.  
  2820.       proc_def->menu_path   = tmp_proc_def->menu_path;
  2821.       proc_def->accelerator = tmp_proc_def->accelerator;
  2822.  
  2823.       tmp_proc_def->menu_path   = NULL;
  2824.       tmp_proc_def->accelerator = NULL;
  2825.  
  2826.       if (superceed_fn)
  2827.         (* superceed_fn) (tmp_proc_def);
  2828.  
  2829.       plug_in_proc_def_destroy (tmp_proc_def, FALSE);
  2830.       return;
  2831.     }
  2832.       else if (!proc_def->menu_path ||
  2833.            (tmp_proc_def->menu_path &&
  2834.         (strcmp (proc_def->menu_path, tmp_proc_def->menu_path) < 0)))
  2835.     {
  2836.       list = g_slist_alloc ();
  2837.       list->data = proc_def;
  2838.  
  2839.       list->next = tmp;
  2840.       if (prev)
  2841.         prev->next = list;
  2842.       else
  2843.         proc_defs = list;
  2844.       return;
  2845.     }
  2846.  
  2847.       prev = tmp;
  2848.       tmp = tmp->next;
  2849.     }
  2850.  
  2851.   proc_defs = g_slist_append (proc_defs, proc_def);
  2852. }
  2853.  
  2854. /* called when plug_in_proc_def_insert causes a proc_def to be
  2855.  * overridden and thus g_free()d.
  2856.  */
  2857. static void
  2858. plug_in_proc_def_dead (void *freed_proc_def)
  2859. {
  2860.   GSList        *tmp;
  2861.   PlugInDef     *plug_in_def;
  2862.   PlugInProcDef *proc_def = freed_proc_def;
  2863.  
  2864.   g_warning ("removing duplicate PDB procedure \"%s\"",
  2865.          proc_def->db_info.name);
  2866.  
  2867.   /* search the plugin list to see if any plugins had references to 
  2868.    * the recently freed proc_def.
  2869.    */
  2870.   for (tmp = plug_in_defs; tmp; tmp = g_slist_next (tmp))
  2871.     {
  2872.       plug_in_def = tmp->data;
  2873.  
  2874.       plug_in_def->proc_defs = g_slist_remove (plug_in_def->proc_defs,
  2875.                            freed_proc_def);
  2876.     }
  2877. }
  2878.  
  2879. static void
  2880. plug_in_proc_def_remove (PlugInProcDef *proc_def)
  2881. {
  2882.   /*  Destroy the menu item  */
  2883.   if (proc_def->menu_path)
  2884.     menus_destroy (proc_def->menu_path);
  2885.  
  2886.   /*  Unregister the procedural database entry  */
  2887.   procedural_db_unregister (proc_def->db_info.name);
  2888.  
  2889.   /*  Remove the defintion from the global list  */
  2890.   proc_defs = g_slist_remove (proc_defs, proc_def);
  2891.  
  2892.   /*  Destroy the definition  */
  2893.   plug_in_proc_def_destroy (proc_def, TRUE);
  2894. }
  2895.  
  2896. static void
  2897. plug_in_proc_def_destroy (PlugInProcDef *proc_def,
  2898.               gboolean       data_only)
  2899. {
  2900.   gint i;
  2901.  
  2902.   if (proc_def->prog)
  2903.     g_free (proc_def->prog);
  2904.   if (proc_def->menu_path)
  2905.     g_free (proc_def->menu_path);
  2906.   if (proc_def->accelerator)
  2907.     g_free (proc_def->accelerator);
  2908.   if (proc_def->extensions)
  2909.     g_free (proc_def->extensions);
  2910.   if (proc_def->prefixes)
  2911.     g_free (proc_def->prefixes);
  2912.   if (proc_def->magics)
  2913.     g_free (proc_def->magics);
  2914.   if (proc_def->image_types)
  2915.     g_free (proc_def->image_types);
  2916.   if (proc_def->db_info.name)
  2917.     g_free (proc_def->db_info.name);
  2918.   if (proc_def->db_info.blurb)
  2919.     g_free (proc_def->db_info.blurb);
  2920.   if (proc_def->db_info.help)
  2921.     g_free (proc_def->db_info.help);
  2922.   if (proc_def->db_info.author)
  2923.     g_free (proc_def->db_info.author);
  2924.   if (proc_def->db_info.copyright)
  2925.     g_free (proc_def->db_info.copyright);
  2926.   if (proc_def->db_info.date)
  2927.     g_free (proc_def->db_info.date);
  2928.  
  2929.   for (i = 0; i < proc_def->db_info.num_args; i++)
  2930.     {
  2931.       if (proc_def->db_info.args[i].name)
  2932.     g_free (proc_def->db_info.args[i].name);
  2933.       if (proc_def->db_info.args[i].description)
  2934.     g_free (proc_def->db_info.args[i].description);
  2935.     }
  2936.  
  2937.   for (i = 0; i < proc_def->db_info.num_values; i++)
  2938.     {
  2939.       if (proc_def->db_info.values[i].name)
  2940.     g_free (proc_def->db_info.values[i].name);
  2941.       if (proc_def->db_info.values[i].description)
  2942.     g_free (proc_def->db_info.values[i].description);
  2943.     }
  2944.  
  2945.   if (proc_def->db_info.args)
  2946.     g_free (proc_def->db_info.args);
  2947.   if (proc_def->db_info.values)
  2948.     g_free (proc_def->db_info.values);
  2949.  
  2950.   if (!data_only)
  2951.     g_free (proc_def);
  2952. }
  2953.  
  2954. static Argument *
  2955. plug_in_temp_run (ProcRecord *proc_rec,
  2956.           Argument   *args,
  2957.           gint        argc)
  2958. {
  2959.   Argument  *return_vals;
  2960.   PlugIn    *plug_in;
  2961.   GPProcRun  proc_run;
  2962.   gint       old_recurse;
  2963.  
  2964.   return_vals = NULL;
  2965.  
  2966.   plug_in = (PlugIn *) proc_rec->exec_method.temporary.plug_in;
  2967.  
  2968.   if (plug_in)
  2969.     {
  2970.       if (plug_in->busy)
  2971.     {
  2972.       return_vals = procedural_db_return_args (proc_rec, FALSE);
  2973.       goto done;
  2974.     }
  2975.  
  2976.       plug_in->busy = TRUE;
  2977.       plug_in_push (plug_in);
  2978.  
  2979.       proc_run.name    = proc_rec->name;
  2980.       proc_run.nparams = argc;
  2981.       proc_run.params  = plug_in_args_to_params (args, argc, FALSE);
  2982.  
  2983.       if (!gp_temp_proc_run_write (current_writechannel, &proc_run) ||
  2984.       !wire_flush (current_writechannel))
  2985.     {
  2986.       return_vals = procedural_db_return_args (proc_rec, FALSE);
  2987.       goto done;
  2988.     }
  2989.  
  2990.       plug_in_pop ();
  2991.  
  2992.       plug_in_params_destroy (proc_run.params, proc_run.nparams, FALSE);
  2993.  
  2994.       old_recurse = plug_in->recurse;
  2995.       plug_in->recurse = TRUE;
  2996.  
  2997. /*       gtk_main (); */
  2998.       
  2999. /*       return_vals = plug_in_get_current_return_vals (proc_rec); */
  3000.       return_vals = procedural_db_return_args (proc_rec, TRUE);
  3001.       plug_in->recurse = old_recurse;
  3002.       plug_in->busy = FALSE;
  3003.     }
  3004.  
  3005. done:
  3006.   return return_vals;
  3007. }
  3008.  
  3009. static Argument*
  3010. plug_in_params_to_args (GPParam *params,
  3011.             gint     nparams,
  3012.             gboolean full_copy)
  3013. {
  3014.   Argument  *args;
  3015.   gchar    **stringarray;
  3016.   guchar    *colorarray;
  3017.   gint count;
  3018.   gint i, j;
  3019.  
  3020.   if (nparams == 0)
  3021.     return NULL;
  3022.  
  3023.   args = g_new (Argument, nparams);
  3024.  
  3025.   for (i = 0; i < nparams; i++)
  3026.     {
  3027.       args[i].arg_type = params[i].type;
  3028.  
  3029.       switch (args[i].arg_type)
  3030.     {
  3031.     case PDB_INT32:
  3032.       args[i].value.pdb_int = params[i].data.d_int32;
  3033.       break;
  3034.     case PDB_INT16:
  3035.       args[i].value.pdb_int = params[i].data.d_int16;
  3036.       break;
  3037.     case PDB_INT8:
  3038.       args[i].value.pdb_int = params[i].data.d_int8;
  3039.       break;
  3040.     case PDB_FLOAT:
  3041.       args[i].value.pdb_float = params[i].data.d_float;
  3042.       break;
  3043.     case PDB_STRING:
  3044.       if (full_copy)
  3045.         args[i].value.pdb_pointer = g_strdup (params[i].data.d_string);
  3046.       else
  3047.         args[i].value.pdb_pointer = params[i].data.d_string;
  3048.       break;
  3049.     case PDB_INT32ARRAY:
  3050.       if (full_copy)
  3051.         {
  3052.           count = args[i-1].value.pdb_int;
  3053.           args[i].value.pdb_pointer = g_new (gint32, count);
  3054.           memcpy (args[i].value.pdb_pointer, params[i].data.d_int32array, count * 4);
  3055.         }
  3056.       else
  3057.         {
  3058.           args[i].value.pdb_pointer = params[i].data.d_int32array;
  3059.         }
  3060.       break;
  3061.     case PDB_INT16ARRAY:
  3062.       if (full_copy)
  3063.         {
  3064.           count = args[i-1].value.pdb_int;
  3065.           args[i].value.pdb_pointer = g_new (gint16, count);
  3066.           memcpy (args[i].value.pdb_pointer, params[i].data.d_int16array, count * 2);
  3067.         }
  3068.       else
  3069.         {
  3070.           args[i].value.pdb_pointer = params[i].data.d_int16array;
  3071.         }
  3072.       break;
  3073.     case PDB_INT8ARRAY:
  3074.       if (full_copy)
  3075.         {
  3076.           count = args[i-1].value.pdb_int;
  3077.           args[i].value.pdb_pointer = g_new (gint8, count);
  3078.           memcpy (args[i].value.pdb_pointer, params[i].data.d_int8array, count);
  3079.         }
  3080.       else
  3081.         {
  3082.           args[i].value.pdb_pointer = params[i].data.d_int8array;
  3083.         }
  3084.       break;
  3085.     case PDB_FLOATARRAY:
  3086.       if (full_copy)
  3087.         {
  3088.           count = args[i-1].value.pdb_int;
  3089.           args[i].value.pdb_pointer = g_new (gdouble, count);
  3090.           memcpy (args[i].value.pdb_pointer, params[i].data.d_floatarray, count * 8);
  3091.         }
  3092.       else
  3093.         {
  3094.           args[i].value.pdb_pointer = params[i].data.d_floatarray;
  3095.         }
  3096.       break;
  3097.     case PDB_STRINGARRAY:
  3098.       if (full_copy)
  3099.         {
  3100.           args[i].value.pdb_pointer = g_new (gchar*, args[i-1].value.pdb_int);
  3101.           stringarray = args[i].value.pdb_pointer;
  3102.  
  3103.           for (j = 0; j < args[i-1].value.pdb_int; j++)
  3104.         stringarray[j] = g_strdup (params[i].data.d_stringarray[j]);
  3105.         }
  3106.       else
  3107.         {
  3108.           args[i].value.pdb_pointer = params[i].data.d_stringarray;
  3109.         }
  3110.       break;
  3111.     case PDB_COLOR:
  3112.       args[i].value.pdb_pointer = g_new (guchar, 3);
  3113.       colorarray    = args[i].value.pdb_pointer;
  3114.       colorarray[0] = params[i].data.d_color.red;
  3115.       colorarray[1] = params[i].data.d_color.green;
  3116.       colorarray[2] = params[i].data.d_color.blue;
  3117.       break;
  3118.     case PDB_REGION:
  3119.       g_message ("the \"region\" arg type is not currently supported");
  3120.       break;
  3121.     case PDB_DISPLAY:
  3122.       args[i].value.pdb_int = params[i].data.d_display;
  3123.       break;
  3124.     case PDB_IMAGE:
  3125.       args[i].value.pdb_int = params[i].data.d_image;
  3126.       break;
  3127.     case PDB_LAYER:
  3128.       args[i].value.pdb_int = params[i].data.d_layer;
  3129.       break;
  3130.     case PDB_CHANNEL:
  3131.       args[i].value.pdb_int = params[i].data.d_channel;
  3132.       break;
  3133.     case PDB_DRAWABLE:
  3134.       args[i].value.pdb_int = params[i].data.d_drawable;
  3135.       break;
  3136.     case PDB_SELECTION:
  3137.       args[i].value.pdb_int = params[i].data.d_selection;
  3138.       break;
  3139.     case PDB_BOUNDARY:
  3140.       args[i].value.pdb_int = params[i].data.d_boundary;
  3141.       break;
  3142.     case PDB_PATH:
  3143.       args[i].value.pdb_int = params[i].data.d_path;
  3144.       break;
  3145.     case PDB_PARASITE:
  3146.       if (full_copy)
  3147.         args[i].value.pdb_pointer =
  3148.           gimp_parasite_copy ((GimpParasite *) &(params[i].data.d_parasite));
  3149.       else
  3150.         args[i].value.pdb_pointer = (void *)&(params[i].data.d_parasite);
  3151.       break;
  3152.     case PDB_STATUS:
  3153.       args[i].value.pdb_int = params[i].data.d_status;
  3154.       break;
  3155.     case PDB_END:
  3156.       break;
  3157.     }
  3158.     }
  3159.  
  3160.   return args;
  3161. }
  3162.  
  3163. static GPParam*
  3164. plug_in_args_to_params (Argument *args,
  3165.             gint      nargs,
  3166.             gboolean  full_copy)
  3167. {
  3168.   GPParam  *params;
  3169.   gchar   **stringarray;
  3170.   guchar   *colorarray;
  3171.   gint i, j;
  3172.  
  3173.   if (nargs == 0)
  3174.     return NULL;
  3175.  
  3176.   params = g_new (GPParam, nargs);
  3177.  
  3178.   for (i = 0; i < nargs; i++)
  3179.     {
  3180.       params[i].type = args[i].arg_type;
  3181.  
  3182.       switch (args[i].arg_type)
  3183.     {
  3184.     case PDB_INT32:
  3185.       params[i].data.d_int32 = args[i].value.pdb_int;
  3186.       break;
  3187.     case PDB_INT16:
  3188.       params[i].data.d_int16 = args[i].value.pdb_int;
  3189.       break;
  3190.     case PDB_INT8:
  3191.       params[i].data.d_int8 = args[i].value.pdb_int;
  3192.       break;
  3193.     case PDB_FLOAT:
  3194.       params[i].data.d_float = args[i].value.pdb_float;
  3195.       break;
  3196.     case PDB_STRING:
  3197.       if (full_copy)
  3198.         params[i].data.d_string = g_strdup (args[i].value.pdb_pointer);
  3199.       else
  3200.         params[i].data.d_string = args[i].value.pdb_pointer;
  3201.       break;
  3202.     case PDB_INT32ARRAY:
  3203.       if (full_copy)
  3204.         {
  3205.           params[i].data.d_int32array = g_new (gint32, params[i-1].data.d_int32);
  3206.           memcpy (params[i].data.d_int32array,
  3207.               args[i].value.pdb_pointer,
  3208.               params[i-1].data.d_int32 * 4);
  3209.         }
  3210.       else
  3211.         {
  3212.           params[i].data.d_int32array = args[i].value.pdb_pointer;
  3213.         }
  3214.       break;
  3215.     case PDB_INT16ARRAY:
  3216.       if (full_copy)
  3217.         {
  3218.           params[i].data.d_int16array = g_new (gint16, params[i-1].data.d_int32);
  3219.           memcpy (params[i].data.d_int16array,
  3220.               args[i].value.pdb_pointer,
  3221.               params[i-1].data.d_int32 * 2);
  3222.         }
  3223.       else
  3224.         {
  3225.           params[i].data.d_int16array = args[i].value.pdb_pointer;
  3226.         }
  3227.       break;
  3228.     case PDB_INT8ARRAY:
  3229.       if (full_copy)
  3230.         {
  3231.           params[i].data.d_int8array = g_new (gint8, params[i-1].data.d_int32);
  3232.           memcpy (params[i].data.d_int8array,
  3233.               args[i].value.pdb_pointer,
  3234.               params[i-1].data.d_int32);
  3235.         }
  3236.       else
  3237.         {
  3238.           params[i].data.d_int8array = args[i].value.pdb_pointer;
  3239.         }
  3240.       break;
  3241.     case PDB_FLOATARRAY:
  3242.       if (full_copy)
  3243.         {
  3244.           params[i].data.d_floatarray = g_new (gdouble, params[i-1].data.d_int32);
  3245.           memcpy (params[i].data.d_floatarray,
  3246.               args[i].value.pdb_pointer,
  3247.               params[i-1].data.d_int32 * 8);
  3248.         }
  3249.       else
  3250.         {
  3251.           params[i].data.d_floatarray = args[i].value.pdb_pointer;
  3252.         }
  3253.       break;
  3254.     case PDB_STRINGARRAY:
  3255.       if (full_copy)
  3256.         {
  3257.           params[i].data.d_stringarray = g_new (gchar*, params[i-1].data.d_int32);
  3258.           stringarray = args[i].value.pdb_pointer;
  3259.  
  3260.           for (j = 0; j < params[i-1].data.d_int32; j++)
  3261.         params[i].data.d_stringarray[j] = g_strdup (stringarray[j]);
  3262.         }
  3263.       else
  3264.         {
  3265.           params[i].data.d_stringarray = args[i].value.pdb_pointer;
  3266.         }
  3267.       break;
  3268.     case PDB_COLOR:
  3269.       colorarray = args[i].value.pdb_pointer;
  3270.       if( colorarray )
  3271.         {
  3272.           params[i].data.d_color.red   = colorarray[0];
  3273.           params[i].data.d_color.green = colorarray[1];
  3274.           params[i].data.d_color.blue  = colorarray[2];
  3275.         }
  3276.       else
  3277.         {
  3278.           params[i].data.d_color.red   = 0;
  3279.           params[i].data.d_color.green = 0;
  3280.           params[i].data.d_color.blue  = 0;
  3281.         }
  3282.       break;
  3283.     case PDB_REGION:
  3284.       g_message ("the \"region\" arg type is not currently supported");
  3285.       break;
  3286.     case PDB_DISPLAY:
  3287.       params[i].data.d_display = args[i].value.pdb_int;
  3288.       break;
  3289.     case PDB_IMAGE:
  3290.       params[i].data.d_image = args[i].value.pdb_int;
  3291.       break;
  3292.     case PDB_LAYER:
  3293.       params[i].data.d_layer = args[i].value.pdb_int;
  3294.       break;
  3295.     case PDB_CHANNEL:
  3296.       params[i].data.d_channel = args[i].value.pdb_int;
  3297.       break;
  3298.     case PDB_DRAWABLE:
  3299.       params[i].data.d_drawable = args[i].value.pdb_int;
  3300.       break;
  3301.     case PDB_SELECTION:
  3302.       params[i].data.d_selection = args[i].value.pdb_int;
  3303.       break;
  3304.     case PDB_BOUNDARY:
  3305.       params[i].data.d_boundary = args[i].value.pdb_int;
  3306.       break;
  3307.     case PDB_PATH:
  3308.       params[i].data.d_path = args[i].value.pdb_int;
  3309.       break;
  3310.     case PDB_PARASITE:
  3311.       if (full_copy)
  3312.         {
  3313.           GimpParasite *tmp;
  3314.  
  3315.           tmp = gimp_parasite_copy (args[i].value.pdb_pointer);
  3316.           if (tmp == NULL)
  3317.         {
  3318.           params[i].data.d_parasite.name  = 0;
  3319.           params[i].data.d_parasite.flags = 0;
  3320.           params[i].data.d_parasite.size  = 0;
  3321.           params[i].data.d_parasite.data  = 0;
  3322.         }
  3323.           else
  3324.         {
  3325.           memcpy (¶ms[i].data.d_parasite, tmp,
  3326.               sizeof (GimpParasite));
  3327.           g_free (tmp);
  3328.         }
  3329.         }
  3330.       else
  3331.         {
  3332.           if (args[i].value.pdb_pointer == NULL)
  3333.         {
  3334.           params[i].data.d_parasite.name  = 0;
  3335.           params[i].data.d_parasite.flags = 0;
  3336.           params[i].data.d_parasite.size  = 0;
  3337.           params[i].data.d_parasite.data  = 0;
  3338.         }
  3339.           else
  3340.         memcpy (¶ms[i].data.d_parasite,
  3341.             (GimpParasite *) (args[i].value.pdb_pointer),
  3342.             sizeof (GimpParasite));
  3343.         }
  3344.       break;
  3345.     case PDB_STATUS:
  3346.       params[i].data.d_status = args[i].value.pdb_int;
  3347.       break;
  3348.     case PDB_END:
  3349.       break;
  3350.     }
  3351.     }
  3352.  
  3353.   return params;
  3354. }
  3355.  
  3356. static void
  3357. plug_in_params_destroy (GPParam *params,
  3358.             gint      nparams,
  3359.             gboolean  full_destroy)
  3360. {
  3361.   gint i, j;
  3362.  
  3363.   for (i = 0; i < nparams; i++)
  3364.     {
  3365.       switch (params[i].type)
  3366.     {
  3367.     case PDB_INT32:
  3368.     case PDB_INT16:
  3369.     case PDB_INT8:
  3370.     case PDB_FLOAT:
  3371.       break;
  3372.     case PDB_STRING:
  3373.       if (full_destroy)
  3374.         g_free (params[i].data.d_string);
  3375.       break;
  3376.     case PDB_INT32ARRAY:
  3377.       if (full_destroy)
  3378.         g_free (params[i].data.d_int32array);
  3379.       break;
  3380.     case PDB_INT16ARRAY:
  3381.       if (full_destroy)
  3382.         g_free (params[i].data.d_int16array);
  3383.       break;
  3384.     case PDB_INT8ARRAY:
  3385.       if (full_destroy)
  3386.         g_free (params[i].data.d_int8array);
  3387.       break;
  3388.     case PDB_FLOATARRAY:
  3389.       if (full_destroy)
  3390.         g_free (params[i].data.d_floatarray);
  3391.       break;
  3392.     case PDB_STRINGARRAY:
  3393.       if (full_destroy)
  3394.         {
  3395.           for (j = 0; j < params[i-1].data.d_int32; j++)
  3396.         g_free (params[i].data.d_stringarray[j]);
  3397.           g_free (params[i].data.d_stringarray);
  3398.         }
  3399.       break;
  3400.     case PDB_COLOR:
  3401.       break;
  3402.     case PDB_REGION:
  3403.       g_message ("the \"region\" arg type is not currently supported");
  3404.       break;
  3405.     case PDB_DISPLAY:
  3406.     case PDB_IMAGE:
  3407.     case PDB_LAYER:
  3408.     case PDB_CHANNEL:
  3409.     case PDB_DRAWABLE:
  3410.     case PDB_SELECTION:
  3411.     case PDB_BOUNDARY:
  3412.     case PDB_PATH:
  3413.       break;
  3414.     case PDB_PARASITE:
  3415.       if (full_destroy)
  3416.         if (params[i].data.d_parasite.data)
  3417.         {
  3418.           g_free (params[i].data.d_parasite.name);
  3419.           g_free (params[i].data.d_parasite.data);
  3420.           params[i].data.d_parasite.name = 0;
  3421.           params[i].data.d_parasite.data = 0;
  3422.         }
  3423.       break;
  3424.     case PDB_STATUS:
  3425.       break;
  3426.     case PDB_END:
  3427.       break;
  3428.     }
  3429.     }
  3430.  
  3431.   g_free (params);
  3432. }
  3433.  
  3434. static void
  3435. plug_in_args_destroy (Argument *args,
  3436.               gint       nargs,
  3437.               gboolean   full_destroy)
  3438. {
  3439.   gchar **stringarray;
  3440.   gint    count;
  3441.   gint    i, j;
  3442.  
  3443.   for (i = 0; i < nargs; i++)
  3444.     {
  3445.       switch (args[i].arg_type)
  3446.     {
  3447.     case PDB_INT32:
  3448.     case PDB_INT16:
  3449.     case PDB_INT8:
  3450.     case PDB_FLOAT:
  3451.       break;
  3452.     case PDB_STRING:
  3453.       if (full_destroy)
  3454.         g_free (args[i].value.pdb_pointer);
  3455.       break;
  3456.     case PDB_INT32ARRAY:
  3457.       if (full_destroy)
  3458.         g_free (args[i].value.pdb_pointer);
  3459.       break;
  3460.     case PDB_INT16ARRAY:
  3461.       if (full_destroy)
  3462.         g_free (args[i].value.pdb_pointer);
  3463.       break;
  3464.     case PDB_INT8ARRAY:
  3465.       if (full_destroy)
  3466.         g_free (args[i].value.pdb_pointer);
  3467.       break;
  3468.     case PDB_FLOATARRAY:
  3469.       if (full_destroy)
  3470.         g_free (args[i].value.pdb_pointer);
  3471.       break;
  3472.     case PDB_STRINGARRAY:
  3473.       if (full_destroy)
  3474.         {
  3475.           count = args[i-1].value.pdb_int;
  3476.           stringarray = args[i].value.pdb_pointer;
  3477.  
  3478.           for (j = 0; j < count; j++)
  3479.         g_free (stringarray[j]);
  3480.  
  3481.           g_free (args[i].value.pdb_pointer);
  3482.         }
  3483.       break;
  3484.     case PDB_COLOR:
  3485.       g_free (args[i].value.pdb_pointer);
  3486.       break;
  3487.     case PDB_REGION:
  3488.       g_message ("the \"region\" arg type is not currently supported");
  3489.       break;
  3490.     case PDB_DISPLAY:
  3491.     case PDB_IMAGE:
  3492.     case PDB_LAYER:
  3493.     case PDB_CHANNEL:
  3494.     case PDB_DRAWABLE:
  3495.     case PDB_SELECTION:
  3496.     case PDB_BOUNDARY:
  3497.     case PDB_PATH:
  3498.       break;
  3499.     case PDB_PARASITE:
  3500.       if (full_destroy)
  3501.         {
  3502.           gimp_parasite_free ((GimpParasite *) (args[i].value.pdb_pointer));
  3503.           args[i].value.pdb_pointer = NULL;
  3504.         }
  3505.       break;
  3506.     case PDB_STATUS:
  3507.       break;
  3508.     case PDB_END:
  3509.       break;
  3510.     }
  3511.     }
  3512.  
  3513.   g_free (args);
  3514. }
  3515.  
  3516. gint
  3517. plug_in_image_types_parse (gchar *image_types)
  3518. {
  3519.   gchar *type_spec = image_types;
  3520.   gint   types = 0;
  3521.  
  3522.   /* 
  3523.    *  If the plug_in registers with image_type == NULL or "", return 0
  3524.    *  By doing so it won't be touched by plug_in_set_menu_sensitivity() 
  3525.    */
  3526.   if (!image_types)
  3527.     return types;
  3528.  
  3529.   while (*image_types)
  3530.     {
  3531.       while (*image_types &&
  3532.          ((*image_types == ' ') ||
  3533.           (*image_types == '\t') ||
  3534.           (*image_types == ',')))
  3535.     image_types++;
  3536.  
  3537.       if (*image_types)
  3538.     {
  3539.       if (strncmp (image_types, "RGBA", 4) == 0)
  3540.         {
  3541.           types |= PLUG_IN_RGBA_IMAGE;
  3542.           image_types += 4;
  3543.         }
  3544.       else if (strncmp (image_types, "RGB*", 4) == 0)
  3545.         {
  3546.           types |= PLUG_IN_RGB_IMAGE | PLUG_IN_RGBA_IMAGE;
  3547.           image_types += 4;
  3548.         }
  3549.       else if (strncmp (image_types, "RGB", 3) == 0)
  3550.         {
  3551.           types |= PLUG_IN_RGB_IMAGE;
  3552.           image_types += 3;
  3553.         }
  3554.       else if (strncmp (image_types, "GRAYA", 5) == 0)
  3555.         {
  3556.           types |= PLUG_IN_GRAYA_IMAGE;
  3557.           image_types += 5;
  3558.         }
  3559.       else if (strncmp (image_types, "GRAY*", 5) == 0)
  3560.         {
  3561.           types |= PLUG_IN_GRAY_IMAGE | PLUG_IN_GRAYA_IMAGE;
  3562.           image_types += 5;
  3563.         }
  3564.       else if (strncmp (image_types, "GRAY", 4) == 0)
  3565.         {
  3566.           types |= PLUG_IN_GRAY_IMAGE;
  3567.           image_types += 4;
  3568.         }
  3569.       else if (strncmp (image_types, "INDEXEDA", 8) == 0)
  3570.         {
  3571.           types |= PLUG_IN_INDEXEDA_IMAGE;
  3572.           image_types += 8;
  3573.         }
  3574.       else if (strncmp (image_types, "INDEXED*", 8) == 0)
  3575.         {
  3576.           types |= PLUG_IN_INDEXED_IMAGE | PLUG_IN_INDEXEDA_IMAGE;
  3577.           image_types += 8;
  3578.         }
  3579.       else if (strncmp (image_types, "INDEXED", 7) == 0)
  3580.         {
  3581.           types |= PLUG_IN_INDEXED_IMAGE;
  3582.           image_types += 7;
  3583.         }
  3584.       else if (strncmp (image_types, "*", 1) == 0)
  3585.         {
  3586.           types |= PLUG_IN_RGB_IMAGE | PLUG_IN_RGBA_IMAGE
  3587.                  | PLUG_IN_GRAY_IMAGE | PLUG_IN_GRAYA_IMAGE
  3588.                  | PLUG_IN_INDEXED_IMAGE | PLUG_IN_INDEXEDA_IMAGE;
  3589.           image_types += 1;
  3590.         }
  3591.       else
  3592.         {
  3593.               g_warning ("image_type contains unrecognizable parts: '%s'", type_spec);
  3594.           while (*image_types &&
  3595.                      ((*image_types != ' ') ||
  3596.                       (*image_types != '\t') ||
  3597.                       (*image_types != ',')))
  3598.         image_types++;
  3599.         }
  3600.     }
  3601.     }
  3602.  
  3603.   return types;
  3604. }
  3605.  
  3606. static void
  3607. plug_in_progress_cancel (GtkWidget *widget,
  3608.              PlugIn    *plug_in)
  3609. {
  3610.   plug_in_destroy (plug_in);
  3611. }
  3612.  
  3613. void
  3614. plug_in_progress_init (PlugIn *plug_in,
  3615.                gchar  *message,
  3616.                gint    gdisp_ID)
  3617. {
  3618.   GDisplay *gdisp = NULL;
  3619.  
  3620.   if (!message)
  3621.     message = plug_in->args[0];
  3622.  
  3623.   if (gdisp_ID > 0) 
  3624.       gdisp = gdisplay_get_ID(gdisp_ID);
  3625.  
  3626.   if (plug_in->progress)
  3627.     plug_in->progress = progress_restart (plug_in->progress, message,
  3628.                       plug_in_progress_cancel, plug_in);
  3629.   else
  3630.     plug_in->progress = progress_start (gdisp, message, TRUE,
  3631.                     plug_in_progress_cancel, plug_in);
  3632. }
  3633.  
  3634. void
  3635. plug_in_progress_update (PlugIn  *plug_in,
  3636.              gdouble  percentage)
  3637. {
  3638.   if (!plug_in->progress)
  3639.     plug_in_progress_init (plug_in, NULL, -1);
  3640.   
  3641.   progress_update (plug_in->progress, percentage);
  3642. }
  3643.